mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Dont' trivial bitcast between differently sized structs.
Really we want to only cast between equally sized types. SIL does not really have a concept of types of the same size so this solution is a workaround (temporary) for acutal code in the standard library which casts a pointer of an UTF16 type to a pointer of an UTF8 type. rdar://18118602 Swift SVN r21470
This commit is contained in:
@@ -409,6 +409,15 @@ forwardAddressValueToUncheckedAddrToLoad(SILValue Address,
|
||||
|
||||
// If the output is trivial, we have a trivial bit cast.
|
||||
if (OutputIsTrivial) {
|
||||
|
||||
// The structs could have different size. We have code in the stdlib that
|
||||
// casts pointers to differently sized integer types. This code prevents
|
||||
// that we bitcast the values.
|
||||
SILType InputTy = UADCI->getOperand().getType();
|
||||
if (OutputTy.getStructOrBoundGenericStruct() &&
|
||||
InputTy.getStructOrBoundGenericStruct())
|
||||
return SILValue();
|
||||
|
||||
CastValue = B.createUncheckedTrivialBitCast(UADCI->getLoc(), StoredValue,
|
||||
OutputTy.getObjectType());
|
||||
} else {
|
||||
|
||||
@@ -1506,6 +1506,12 @@ visitPointerToAddressInst(PointerToAddressInst *PTAI) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static bool areBothStructs(SILType Ty1, SILType Ty2) {
|
||||
if (Ty1.getStructOrBoundGenericStruct() && Ty2.getStructOrBoundGenericStruct())
|
||||
return true;
|
||||
else return false;
|
||||
}
|
||||
|
||||
SILInstruction *
|
||||
SILCombiner::visitUncheckedAddrCastInst(UncheckedAddrCastInst *UADCI) {
|
||||
SILModule &Mod = UADCI->getModule();
|
||||
@@ -1546,6 +1552,13 @@ SILCombiner::visitUncheckedAddrCastInst(UncheckedAddrCastInst *UADCI) {
|
||||
if (InputIsTrivial && !OutputIsTrivial)
|
||||
return nullptr;
|
||||
|
||||
// The structs could have different size. We have code in the stdlib that
|
||||
// casts pointers to differently sized integer types. This code prevents that
|
||||
// we bitcast the values.
|
||||
if (InputTy.getStructOrBoundGenericStruct() &&
|
||||
OutputTy.getStructOrBoundGenericStruct())
|
||||
return nullptr;
|
||||
|
||||
// For each user U of the unchecked_addr_cast...
|
||||
for (auto U : UADCI->getUses())
|
||||
// Check if it is load. If it is not a load, bail...
|
||||
|
||||
@@ -638,3 +638,23 @@ bb2:
|
||||
%9999 = tuple()
|
||||
return %9999 : $()
|
||||
}
|
||||
|
||||
struct C {
|
||||
var i : Builtin.Int16
|
||||
}
|
||||
|
||||
// Don't bitcast differently sized structs.
|
||||
// CHECK-LABEL: sil @store_to_load_forward_unchecked_addr_cast_different_sized_struct
|
||||
// CHECK-NOT: unchecked_trivial_bit_cast
|
||||
// CHECK: return
|
||||
|
||||
sil @store_to_load_forward_unchecked_addr_cast_different_sized_struct : $@thin (A) -> () {
|
||||
bb0(%0 : $A):
|
||||
%1 = alloc_stack $A
|
||||
store %0 to %1#1 : $*A
|
||||
%2 = unchecked_addr_cast %1#1 : $*A to $*C
|
||||
%3 = load %2 : $*C
|
||||
dealloc_stack %1#0 : $*@local_storage A
|
||||
%9999 = tuple()
|
||||
return %9999 : $()
|
||||
}
|
||||
|
||||
@@ -1704,3 +1704,25 @@ bb0(%0 : $Builtin.NativeObject):
|
||||
return %3 : $Builtin.NativeObject
|
||||
}
|
||||
|
||||
struct FakeInt16 {
|
||||
var val : Builtin.Int16
|
||||
}
|
||||
|
||||
struct FakeInt32 {
|
||||
var val : Builtin.Int32
|
||||
}
|
||||
|
||||
// Don't promote this to an unchecked_trivial_bit_cast.
|
||||
|
||||
// CHECK-LABEL: sil @unchecked_addr_cast_of_different_size_structs
|
||||
// CHECK-NOT: unchecked_trivial_bit_cast
|
||||
// CHECK: return
|
||||
|
||||
sil @unchecked_addr_cast_of_different_size_structs : $@thin (@inout FakeInt32) -> Builtin.Int16 {
|
||||
bb0(%0 : $*FakeInt32):
|
||||
%1 = unchecked_addr_cast %0 : $*FakeInt32 to $*FakeInt16
|
||||
%2 = load %1 : $*FakeInt16
|
||||
%3 = struct_extract %2 : $FakeInt16, #FakeInt16.val
|
||||
return %3 : $Builtin.Int16
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user