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:
Arnold Schwaighofer
2014-08-27 00:05:04 +00:00
parent 0085b94509
commit ef3adb2186
4 changed files with 64 additions and 0 deletions

View File

@@ -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 {

View File

@@ -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...

View File

@@ -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 : $()
}

View File

@@ -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
}