IRGen: Remove initializeBufferWithTakeOfBuffer in favor of memcpy

And update the existential container's initializeWithTake implementation
in the runtime. After only allowing bitwise takable values in the
inline buffer we can use memcpy to move existential container values.

rdar://31414907
SR-343
This commit is contained in:
Arnold Schwaighofer
2018-05-22 10:22:49 -07:00
parent d05f611b6d
commit 6267860a7e
36 changed files with 121 additions and 496 deletions

View File

@@ -172,14 +172,6 @@ FUNCTION_VALUE_WITNESS(assignWithTake,
MUTABLE_VALUE_TYPE,
(MUTABLE_VALUE_TYPE, MUTABLE_VALUE_TYPE, TYPE_TYPE))
/// T *(*initializeBufferWithTakeOfBuffer)(B *dest, B *src, M *self);
/// Given an invalid buffer, initialize it by taking the value out of
/// the source buffer.
FUNCTION_VALUE_WITNESS(initializeBufferWithTakeOfBuffer,
InitializeBufferWithTakeOfBuffer,
MUTABLE_VALUE_TYPE,
(MUTABLE_BUFFER_TYPE, MUTABLE_BUFFER_TYPE, TYPE_TYPE))
/// unsigned (*getEnumTagSinglePayload)(const T* enum, UINT_TYPE emptyCases)
/// Given an instance of valid single payload enum with a payload of this
/// witness table's type (e.g Optional<ThisType>) , get the tag of the enum.

View File

@@ -343,16 +343,11 @@ public:
void initializeWithTake(IRGenFunction &IGF, Address dest, Address src,
SILType T, bool isOutlined) const override {
if (isOutlined) {
llvm::Value *metadata = copyType(IGF, dest, src);
auto layout = getLayout();
// Project down to the buffers and ask the witnesses to do a
// take-initialize.
Address srcBuffer = layout.projectExistentialBuffer(IGF, src);
Address destBuffer = layout.projectExistentialBuffer(IGF, dest);
emitInitializeBufferWithTakeOfBufferCall(IGF, metadata, destBuffer,
srcBuffer);
// memcpy the existential container. This is safe because: either the
// value is stored inline and is therefore by convention bitwise takable
// or the value is stored in a reference counted heap buffer, in which
// case a memcpy of the reference is also correct.
IGF.emitMemCpy(dest, src, getLayout().getSize(IGF.IGM));
} else {
// Create an outlined function to avoid explosion
OutliningMetadataCollector collector(IGF);

View File

@@ -66,9 +66,7 @@ static llvm::Type *createWitnessType(IRGenModule &IGM, ValueWitness index) {
}
// T *(*initializeBufferWithCopyOfBuffer)(B *dest, B *src, M *self);
// T *(*initializeBufferWithTakeOfBuffer)(B *dest, B *src, M *self);
case ValueWitness::InitializeBufferWithCopyOfBuffer:
case ValueWitness::InitializeBufferWithTakeOfBuffer: {
case ValueWitness::InitializeBufferWithCopyOfBuffer: {
llvm::Type *bufPtrTy = IGM.getFixedBufferTy()->getPointerTo(0);
llvm::Type *args[] = { bufPtrTy, bufPtrTy, IGM.TypeMetadataPtrTy };
return llvm::FunctionType::get(IGM.OpaquePtrTy, args, /*isVarArg*/ false);
@@ -212,7 +210,6 @@ static llvm::AttributeList getValueWitnessAttrs(IRGenModule &IGM,
// These have two arguments and they don't alias each other.
case ValueWitness::AssignWithTake:
case ValueWitness::InitializeBufferWithCopyOfBuffer:
case ValueWitness::InitializeBufferWithTakeOfBuffer:
case ValueWitness::InitializeWithCopy:
case ValueWitness::InitializeWithTake:
return attrs.addAttribute(ctx, 1, llvm::Attribute::NoAlias)
@@ -259,8 +256,6 @@ static StringRef getValueWitnessLabel(ValueWitness index) {
return "initializeWithCopy";
case ValueWitness::InitializeWithTake:
return "initializeWithTake";
case ValueWitness::InitializeBufferWithTakeOfBuffer:
return "initializeBufferWithTakeOfBuffer";
case ValueWitness::Size:
return "size";
case ValueWitness::Flags:
@@ -417,31 +412,6 @@ irgen::emitInitializeBufferWithCopyOfBufferCall(IRGenFunction &IGF,
return call;
}
llvm::Value *
irgen::emitInitializeBufferWithTakeOfBufferCall(IRGenFunction &IGF,
SILType T,
Address destBuffer,
Address srcBuffer) {
auto metadata = IGF.emitTypeMetadataRefForLayout(T);
return emitInitializeBufferWithTakeOfBufferCall(IGF, metadata,
destBuffer, srcBuffer);
}
/// Emit a call to do an 'initializeBufferWithTakeOfBuffer' operation.
llvm::Value *
irgen::emitInitializeBufferWithTakeOfBufferCall(IRGenFunction &IGF,
llvm::Value *metadata,
Address destBuffer,
Address srcBuffer) {
auto copyFn = emitLoadOfValueWitnessFunctionFromMetadata(IGF, metadata,
ValueWitness::InitializeBufferWithTakeOfBuffer);
llvm::CallInst *call =
IGF.Builder.CreateCall(copyFn,
{destBuffer.getAddress(), srcBuffer.getAddress(), metadata});
return call;
}
/// Emit a dynamic alloca call to allocate enough memory to hold an object of
/// type 'T' and an optional llvm.stackrestore point if 'isInEntryBlock' is
/// false.

View File

@@ -58,18 +58,6 @@ namespace irgen {
Address destBuffer,
Address srcBuffer);
/// Emit a call to do an 'initializeBufferWithTakeOfBuffer' operation.
llvm::Value *emitInitializeBufferWithTakeOfBufferCall(IRGenFunction &IGF,
llvm::Value *metadata,
Address destBuffer,
Address srcBuffer);
/// Emit a call to do an 'initializeBufferWithTakeOfBuffer' operation.
llvm::Value *emitInitializeBufferWithTakeOfBufferCall(IRGenFunction &IGF,
SILType T,
Address destBuffer,
Address srcBuffer);
/// Emit a call to do an 'initializeWithCopy' operation.
void emitInitializeWithCopyCall(IRGenFunction &IGF,
SILType T,

View File

@@ -323,22 +323,6 @@ protected:
public:
using super::getStorageType;
Address initializeBufferWithTakeOfBuffer(IRGenFunction &IGF,
Address destBuffer,
Address srcBuffer,
SILType type) const override {
if (auto field = getUniqueNonEmptyField()) {
auto &fieldTI = field->getTypeInfo();
Address fieldResult =
fieldTI.initializeBufferWithTakeOfBuffer(IGF, destBuffer, srcBuffer,
field->getType(IGF.IGM, type));
return IGF.Builder.CreateElementBitCast(fieldResult, getStorageType());
} else {
return super::initializeBufferWithTakeOfBuffer(IGF, destBuffer,
srcBuffer, type);
}
}
Address initializeBufferWithCopyOfBuffer(IRGenFunction &IGF,
Address destBuffer,
Address srcBuffer,

View File

@@ -56,7 +56,6 @@ const char *irgen::getValueWitnessName(ValueWitness witness) {
CASE(InitializeBufferWithCopyOfBuffer)
CASE(InitializeWithCopy)
CASE(InitializeWithTake)
CASE(InitializeBufferWithTakeOfBuffer)
CASE(StoreExtraInhabitant)
CASE(GetExtraInhabitantIndex)
CASE(GetEnumTag)
@@ -331,47 +330,6 @@ static Address emitDefaultInitializeBufferWithCopyOfBuffer(
}
}
/// Emit an 'initializeBufferWithTakeOfBuffer' operation.
/// Returns the address of the destination object.
static Address
emitDefaultInitializeBufferWithTakeOfBuffer(IRGenFunction &IGF,
Address destBuffer,
Address srcBuffer,
SILType T,
const TypeInfo &type,
FixedPacking packing) {
switch (packing) {
case FixedPacking::Dynamic:
// Special-case dynamic packing in order to thread the jumps.
return emitForDynamicPacking(IGF,
&emitDefaultInitializeBufferWithTakeOfBuffer,
T, type, destBuffer, srcBuffer);
case FixedPacking::OffsetZero: {
// Both of these allocations/projections should be no-ops.
Address destObject =
emitDefaultAllocateBuffer(IGF, destBuffer, T, type, packing);
Address srcObject =
emitDefaultProjectBuffer(IGF, srcBuffer, T, type, packing);
type.initializeWithTake(IGF, destObject, srcObject, T, true);
return destObject;
}
case FixedPacking::Allocate: {
// Just copy the out-of-line storage pointers.
srcBuffer = IGF.Builder.CreateBitCast(
srcBuffer, IGF.IGM.RefCountedPtrTy->getPointerTo());
llvm::Value *addr = IGF.Builder.CreateLoad(srcBuffer);
destBuffer = IGF.Builder.CreateBitCast(
destBuffer, IGF.IGM.RefCountedPtrTy->getPointerTo());
IGF.Builder.CreateStore(addr, destBuffer);
return emitDefaultProjectBuffer(IGF, destBuffer, T, type, packing);
}
}
llvm_unreachable("bad fixed packing");
}
// Metaprogram some of the common boilerplate here:
// - the default implementation in TypeInfo
// - the value-witness emitter which tries to avoid some dynamic
@@ -392,8 +350,6 @@ static Address emit##TITLE(IRGenFunction &IGF, Address dest, Address src, \
}
DEFINE_BINARY_BUFFER_OP(initializeBufferWithCopyOfBuffer,
InitializeBufferWithCopyOfBuffer)
DEFINE_BINARY_BUFFER_OP(initializeBufferWithTakeOfBuffer,
InitializeBufferWithTakeOfBuffer)
#undef DEFINE_BINARY_BUFFER_OP
@@ -532,19 +488,6 @@ static void buildValueWitnessFunction(IRGenModule &IGM,
return;
}
case ValueWitness::InitializeBufferWithTakeOfBuffer: {
Address dest = getArgAsBuffer(IGF, argv, "dest");
Address src = getArgAsBuffer(IGF, argv, "src");
getArgAsLocalSelfTypeMetadata(IGF, argv, abstractType);
Address result =
emitInitializeBufferWithTakeOfBuffer(IGF, dest, src, concreteType,
type, packing);
result = IGF.Builder.CreateBitCast(result, IGF.IGM.OpaquePtrTy);
IGF.Builder.CreateRet(result.getAddress());
return;
}
case ValueWitness::InitializeWithCopy: {
Address dest = getArgAs(IGF, argv, type, "dest");
Address src = getArgAs(IGF, argv, type, "src");
@@ -805,38 +748,6 @@ static llvm::Constant *getMemCpyFunction(IRGenModule &IGM,
});
}
/// Return a function which takes two buffer arguments, copies
/// a pointer from the second to the first, and returns the pointer.
static llvm::Constant *
getCopyOutOfLineBoxPointerFunction(IRGenModule &IGM,
const FixedTypeInfo &fixedTI) {
llvm::Type *argTys[] = { IGM.Int8PtrPtrTy, IGM.Int8PtrPtrTy,
IGM.TypeMetadataPtrTy };
llvm::SmallString<40> name;
{
llvm::raw_svector_ostream nameStream(name);
nameStream << "__swift_copy_outline_existential_box_pointer";
nameStream << fixedTI.getFixedAlignment().getValue();
}
return IGM.getOrCreateHelperFunction(
name, IGM.Int8PtrTy, argTys, [&](IRGenFunction &IGF) {
auto it = IGF.CurFn->arg_begin();
Address dest(&*it++, IGM.getPointerAlignment());
Address src(&*it++, IGM.getPointerAlignment());
auto *ptr = IGF.Builder.CreateLoad(src);
IGF.Builder.CreateStore(ptr, dest);
auto *alignmentMask = fixedTI.getStaticAlignmentMask(IGM);
auto *heapHeaderSize = llvm::ConstantInt::get(
IGM.SizeTy, IGM.RefCountedStructSize.getValue());
auto *startOffset = IGF.Builder.CreateAnd(
IGF.Builder.CreateAdd(heapHeaderSize, alignmentMask),
IGF.Builder.CreateNot(alignmentMask));
auto *objectAddr =
IGF.emitByteOffsetGEP(ptr, startOffset, IGM.Int8Ty);
IGF.Builder.CreateRet(objectAddr);
});
}
/// Find a witness to the fact that a type is a value type.
/// Always adds an i8*.
static void addValueWitness(IRGenModule &IGM,
@@ -870,17 +781,6 @@ static void addValueWitness(IRGenModule &IGM,
}
goto standard;
case ValueWitness::InitializeBufferWithTakeOfBuffer:
if (packing == FixedPacking::Allocate) {
return addFunction(getCopyOutOfLineBoxPointerFunction(
IGM, cast<FixedTypeInfo>(concreteTI)));
} else
if (packing == FixedPacking::OffsetZero &&
concreteTI.isBitwiseTakable(ResilienceExpansion::Maximal)) {
return addFunction(getMemCpyFunction(IGM, concreteTI));
}
goto standard;
case ValueWitness::InitializeWithTake:
if (concreteTI.isBitwiseTakable(ResilienceExpansion::Maximal)) {
return addFunction(getMemCpyFunction(IGM, concreteTI));

View File

@@ -45,7 +45,6 @@ std::string IRGenMangler::mangleValueWitness(Type type, ValueWitness witness) {
GET_MANGLING(AssignWithCopy) \
GET_MANGLING(InitializeWithTake) \
GET_MANGLING(AssignWithTake) \
GET_MANGLING(InitializeBufferWithTakeOfBuffer) \
GET_MANGLING(GetEnumTagSinglePayload) \
GET_MANGLING(StoreEnumTagSinglePayload) \
GET_MANGLING(StoreExtraInhabitant) \

View File

@@ -88,13 +88,6 @@ public:
return this->getAddressForPointer(addr);
}
Address initializeBufferWithTakeOfBuffer(IRGenFunction &IGF,
Address dest, Address src,
SILType T) const override {
auto addr = emitInitializeBufferWithTakeOfBufferCall(IGF, T, dest, src);
return this->getAddressForPointer(addr);
}
void initializeWithCopy(IRGenFunction &IGF, Address dest, Address src,
SILType T, bool isOutlined) const override {
emitInitializeWithCopyCall(IGF, T, dest, src);

View File

@@ -370,23 +370,6 @@ public:
Address srcBuffer,
SILType T) const;
/// Perform a take-initialization from the given fixed-size buffer
/// into an uninitialized fixed-size buffer, allocating the buffer if
/// necessary and deallocating the destination buffer. Returns the
/// address of the value inside the destination buffer.
///
/// This is equivalent to:
/// auto srcAddress = projectBuffer(IGF, srcBuffer, T);
/// initializeBufferWithTake(IGF, destBuffer, srcAddress, T);
/// deallocateBuffer(IGF, srcBuffer, T);
/// but may be able to re-use the buffer from the source buffer, and may
/// be more efficient for dynamic types, since it uses a single
/// value witness call.
virtual Address initializeBufferWithTakeOfBuffer(IRGenFunction &IGF,
Address destBuffer,
Address srcBuffer,
SILType T) const;
/// Take-initialize an address from a parameter explosion.
virtual void initializeFromParams(IRGenFunction &IGF, Explosion &params,
Address src, SILType T,

View File

@@ -107,20 +107,9 @@ struct LLVM_LIBRARY_VISIBILITY OpaqueExistentialBoxBase
static Container *initializeWithTake(Container *dest, Container *src,
A... args) {
src->copyTypeInto(dest, args...);
auto *type = src->getType();
auto *vwt = type->getValueWitnesses();
if (vwt->isValueInline()) {
auto *destValue =
reinterpret_cast<OpaqueValue *>(dest->getBuffer(args...));
auto *srcValue =
reinterpret_cast<OpaqueValue *>(src->getBuffer(args...));
type->vw_initializeWithTake(destValue, srcValue);
} else {
// initWithTake of the reference to the cow box.
copyReference(dest, src, Dest::Init, Source::Take, args...);
}
auto from = src->getBuffer(args...);
auto to = dest->getBuffer(args...);
memcpy(to, from, sizeof(ValueBuffer));
return dest;
}

View File

@@ -1057,23 +1057,6 @@ static OpaqueValue *tuple_initializeBufferWithCopyOfBuffer(ValueBuffer *dest,
return tuple_projectBuffer<IsPOD, IsInline>(dest, metatype);
}
/// Generic tuple value witness for 'initializeBufferWithTakeOfBuffer'.
template <bool IsPOD, bool IsInline>
static OpaqueValue *tuple_initializeBufferWithTakeOfBuffer(ValueBuffer *dest,
ValueBuffer *src,
const Metadata *metatype) {
assert(IsPOD == tuple_getValueWitnesses(metatype)->isPOD());
assert(IsInline == tuple_getValueWitnesses(metatype)->isValueInline());
if (IsInline) {
return tuple_initializeWithTake<IsPOD, IsInline>(
tuple_projectBuffer<IsPOD, IsInline>(dest, metatype),
tuple_projectBuffer<IsPOD, IsInline>(src, metatype), metatype);
}
auto *srcReference = *reinterpret_cast<HeapObject**>(src);
*reinterpret_cast<HeapObject**>(dest) = srcReference;
return tuple_projectBuffer<IsPOD, IsInline>(dest, metatype);
}
template <bool IsPOD, bool IsInline>
static unsigned tuple_getEnumTagSinglePayload(const OpaqueValue *enumAddr,
unsigned numEmptyCases,
@@ -1560,20 +1543,6 @@ static OpaqueValue *pod_indirect_initializeBufferWithCopyOfBuffer(
return reinterpret_cast<OpaqueValue *>(bytePtr + byteOffset);
}
static OpaqueValue *pod_indirect_initializeBufferWithTakeOfBuffer(
ValueBuffer *dest, ValueBuffer *src, const Metadata *self) {
auto wtable = self->getValueWitnesses();
auto *srcReference = *reinterpret_cast<HeapObject**>(src);
*reinterpret_cast<HeapObject**>(dest) = srcReference;
// Project the address of the value in the buffer.
unsigned alignMask = wtable->getAlignmentMask();
// Compute the byte offset of the object in the box.
unsigned byteOffset = (sizeof(HeapObject) + alignMask) & ~alignMask;
auto *bytePtr = reinterpret_cast<char *>(srcReference);
return reinterpret_cast<OpaqueValue *>(bytePtr + byteOffset);
}
static void pod_noop(void *object, const Metadata *self) {
}
#define pod_direct_destroy \
@@ -1590,9 +1559,6 @@ static OpaqueValue *pod_direct_initializeWithCopy(OpaqueValue *dest,
#define pod_direct_initializeBufferWithCopyOfBuffer \
pointer_function_cast<value_witness_types::initializeBufferWithCopyOfBuffer> \
(pod_direct_initializeWithCopy)
#define pod_direct_initializeBufferWithTakeOfBuffer \
pointer_function_cast<value_witness_types::initializeBufferWithTakeOfBuffer> \
(pod_direct_initializeWithCopy)
#define pod_direct_assignWithCopy pod_direct_initializeWithCopy
#define pod_indirect_assignWithCopy pod_direct_initializeWithCopy
#define pod_direct_initializeWithTake pod_direct_initializeWithCopy
@@ -1705,23 +1671,12 @@ void swift::installCommonValueWitnesses(const TypeLayout &layout,
// Use POD value witnesses for operations that do an initializeWithTake.
if (flags.isInlineStorage()) {
vwtable->initializeWithTake = pod_direct_initializeWithTake;
vwtable->initializeBufferWithTakeOfBuffer
= pod_direct_initializeBufferWithTakeOfBuffer;
} else {
vwtable->initializeWithTake = pod_indirect_initializeWithTake;
vwtable->initializeBufferWithTakeOfBuffer
= pod_indirect_initializeBufferWithTakeOfBuffer;
}
return;
}
if (!flags.isInlineStorage()) {
// For values stored out-of-line, initializeBufferWithTakeOfBuffer is
// always a memcpy.
vwtable->initializeBufferWithTakeOfBuffer
= pod_indirect_initializeBufferWithTakeOfBuffer;
return;
}
}
/***************************************************************************/

View File

@@ -642,13 +642,6 @@ struct BufferValueWitnesses<Impl, isBitwiseTakable, Size, Alignment,
: BufferValueWitnessesBase<Impl> {
static constexpr bool isInline = true;
static OpaqueValue *initializeBufferWithTakeOfBuffer(ValueBuffer *dest,
ValueBuffer *src,
const Metadata *self) {
return Impl::initializeWithTake(reinterpret_cast<OpaqueValue*>(dest),
reinterpret_cast<OpaqueValue*>(src),
self);
}
static OpaqueValue *initializeBufferWithCopyOfBuffer(ValueBuffer *dest,
ValueBuffer *src,
const Metadata *self) {
@@ -665,21 +658,6 @@ struct BufferValueWitnesses<Impl, isBitwiseTakable, Size, Alignment,
: BufferValueWitnessesBase<Impl> {
static constexpr bool isInline = false;
static OpaqueValue *initializeBufferWithTakeOfBuffer(ValueBuffer *dest,
ValueBuffer *src,
const Metadata *self) {
auto wtable = self->getValueWitnesses();
auto *srcReference = *reinterpret_cast<HeapObject **>(src);
*reinterpret_cast<HeapObject **>(dest) = srcReference;
// Project the address of the value in the buffer.
unsigned alignMask = wtable->getAlignmentMask();
// Compute the byte offset of the object in the box.
unsigned byteOffset = (sizeof(HeapObject) + alignMask) & ~alignMask;
auto *bytePtr = reinterpret_cast<char *>(srcReference);
return reinterpret_cast<OpaqueValue *>(bytePtr + byteOffset);
}
static OpaqueValue *initializeBufferWithCopyOfBuffer(ValueBuffer *dest,
ValueBuffer *src,
const Metadata *self) {
@@ -700,26 +678,6 @@ struct BufferValueWitnesses<Impl, isBitwiseTakable, Size, Alignment,
/// fixed in size.
template <class Impl, bool IsKnownAllocated>
struct NonFixedBufferValueWitnesses : BufferValueWitnessesBase<Impl> {
static OpaqueValue *initializeBufferWithTakeOfBuffer(ValueBuffer *dest,
ValueBuffer *src,
const Metadata *self) {
auto vwtable = self->getValueWitnesses();
(void)vwtable;
if (!IsKnownAllocated && vwtable->isValueInline()) {
return Impl::initializeWithTake(reinterpret_cast<OpaqueValue *>(dest),
reinterpret_cast<OpaqueValue *>(src),
self);
} else {
auto reference = src->PrivateData[0];
dest->PrivateData[0] = reference;
// Project the address of the value in the buffer.
unsigned alignMask = vwtable->getAlignmentMask();
// Compute the byte offset of the object in the box.
unsigned byteOffset = (sizeof(HeapObject) + alignMask) & ~alignMask;
auto *bytePtr = reinterpret_cast<char *>(reference);
return reinterpret_cast<OpaqueValue *>(bytePtr + byteOffset);
}
}
static OpaqueValue *initializeBufferWithCopyOfBuffer(ValueBuffer *dest,
ValueBuffer *src,

View File

@@ -225,12 +225,12 @@ func sizeof_alignof_test() {
// CHECK: define hidden {{.*}}void @"$S8builtins27generic_sizeof_alignof_testyyxlF"
func generic_sizeof_alignof_test<T>(_: T) {
// CHECK: [[T0:%.*]] = getelementptr inbounds i8*, i8** [[T:%.*]], i32 9
// CHECK: [[T0:%.*]] = getelementptr inbounds i8*, i8** [[T:%.*]], i32 8
// CHECK-NEXT: [[T1:%.*]] = load i8*, i8** [[T0]]
// CHECK-NEXT: [[SIZE:%.*]] = ptrtoint i8* [[T1]] to i64
// CHECK-NEXT: store i64 [[SIZE]], i64* [[S:%.*]]
var s = Builtin.sizeof(T.self)
// CHECK: [[T0:%.*]] = getelementptr inbounds i8*, i8** [[T:%.*]], i32 10
// CHECK: [[T0:%.*]] = getelementptr inbounds i8*, i8** [[T:%.*]], i32 9
// CHECK-NEXT: [[T1:%.*]] = load i8*, i8** [[T0]]
// CHECK-NEXT: [[T2:%.*]] = ptrtoint i8* [[T1]] to i64
// CHECK-NEXT: [[T3:%.*]] = and i64 [[T2]], 65535
@@ -241,7 +241,7 @@ func generic_sizeof_alignof_test<T>(_: T) {
// CHECK: define hidden {{.*}}void @"$S8builtins21generic_strideof_testyyxlF"
func generic_strideof_test<T>(_: T) {
// CHECK: [[T0:%.*]] = getelementptr inbounds i8*, i8** [[T:%.*]], i32 11
// CHECK: [[T0:%.*]] = getelementptr inbounds i8*, i8** [[T:%.*]], i32 10
// CHECK-NEXT: [[T1:%.*]] = load i8*, i8** [[T0]]
// CHECK-NEXT: [[STRIDE:%.*]] = ptrtoint i8* [[T1]] to i64
// CHECK-NEXT: store i64 [[STRIDE]], i64* [[S:%.*]]
@@ -771,7 +771,7 @@ func isUniqueIUO(_ ref: inout Builtin.NativeObject?) -> Bool {
// CHECK-LABEL: define {{.*}} @{{.*}}generic_ispod_test
func generic_ispod_test<T>(_: T) {
// CHECK: [[T0:%.*]] = getelementptr inbounds i8*, i8** [[T:%.*]], i32 10
// CHECK: [[T0:%.*]] = getelementptr inbounds i8*, i8** [[T:%.*]], i32 9
// CHECK-NEXT: [[T1:%.*]] = load i8*, i8** [[T0]]
// CHECK-NEXT: [[FLAGS:%.*]] = ptrtoint i8* [[T1]] to i64
// CHECK-NEXT: [[ISNOTPOD:%.*]] = and i64 [[FLAGS]], 65536

View File

@@ -127,11 +127,11 @@ import Swift
// CHECK: @"$S4enum16DynamicSingletonOMP" = internal constant <{ {{.*}} }> <{
// CHECK-SAME: @"$S4enum16DynamicSingletonOMi"
// CHECK-SAME: [18 x i8*]* @"$S4enum16DynamicSingletonOWV"
// CHECK-SAME: [17 x i8*]* @"$S4enum16DynamicSingletonOWV"
// -- No-payload enums have extra inhabitants in
// their value witness table.
// CHECK: @"$S4enum10NoPayloadsOWV" = internal constant [18 x i8*] [
// CHECK: @"$S4enum10NoPayloadsOWV" = internal constant [17 x i8*] [
// -- ...
// -- size
// CHECK-SAME: i8* inttoptr ([[WORD:i32|i64]] 1 to i8*),
@@ -149,7 +149,7 @@ import Swift
// -- Single-payload enums take unused extra inhabitants from their payload
// as their own.
// CHECK: @"$S4enum19SinglePayloadNestedOWV" = internal constant [18 x i8*] [
// CHECK: @"$S4enum19SinglePayloadNestedOWV" = internal constant [17 x i8*] [
// -- ...
// -- size
// CHECK-SAME: i8* inttoptr ([[WORD]] 1 to i8*),
@@ -165,16 +165,16 @@ import Swift
// CHECK-SAME: i8* bitcast (i32 (%swift.opaque*, %swift.type*)* @"$S4enum19SinglePayloadNestedOwxg" to i8*)
// CHECK-SAME: ]
// CHECK: @"$S4enum20DynamicSinglePayloadOWV" = internal constant [18 x i8*] [
// CHECK: @"$S4enum20DynamicSinglePayloadOWV" = internal constant [17 x i8*] [
// CHECK-SAME: i8* null
// CHECK-SAME: i8* bitcast (void (%swift.opaque*, i32, %swift.type*)* @"$S4enum20DynamicSinglePayloadOwxs" to i8*)
// CHECK-SAME: i8* bitcast (i32 (%swift.opaque*, %swift.type*)* @"$S4enum20DynamicSinglePayloadOwxg" to i8*)
// CHECK: @"$S4enum20DynamicSinglePayloadOMP" = internal constant <{ {{.*}} }> <{
// CHECK-SAME: @"$S4enum20DynamicSinglePayloadOMi"
// CHECK-SAME: [18 x i8*]* @"$S4enum20DynamicSinglePayloadOWV"
// CHECK-SAME: [17 x i8*]* @"$S4enum20DynamicSinglePayloadOWV"
// CHECK: @"$S4enum18MultiPayloadNestedOWV" = internal constant [18 x i8*] [
// CHECK: @"$S4enum18MultiPayloadNestedOWV" = internal constant [17 x i8*] [
// -- size
// CHECK-32-SAME: i8* inttoptr ([[WORD]] 5 to i8*),
// CHECK-64-SAME: i8* inttoptr ([[WORD]] 9 to i8*),
@@ -1209,7 +1209,7 @@ enum DynamicSinglePayload<T> {
// CHECK: [[TMP:%.*]] = bitcast %swift.type* %T to i8***
// CHECK: [[TMP2:%.*]] = getelementptr inbounds i8**, i8*** [[TMP]], i{{.*}} -1
// CHECK: [[VWT:%.*]] = load i8**, i8*** [[TMP2]]
// CHECK: [[ENUMADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 7
// CHECK: [[ENUMADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 6
// CHECK: [[WITNESS:%.*]] = load i8*, i8** [[ENUMADDR]]
// CHECK: %getEnumTagSinglePayload = bitcast i8* [[WITNESS]] to i32 (%swift.opaque*, i32, %swift.type*)*
// CHECK: [[CASE_INDEX:%.*]] = call i32 %getEnumTagSinglePayload(%swift.opaque* noalias [[OPAQUE_ENUM]], i32 3, %swift.type* %T)
@@ -1240,7 +1240,7 @@ end:
// CHECK: [[TMP:%.*]] = bitcast %swift.type* %T to i8***
// CHECK: [[TMP2:%.*]] = getelementptr inbounds i8**, i8*** [[TMP]], i{{.*}} -1
// CHECK: [[VWT:%.*]] = load i8**, i8*** [[TMP2]]
// CHECK: [[ENUMADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 8
// CHECK: [[ENUMADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 7
// CHECK: [[WITNESS:%.*]] = load i8*, i8** [[ENUMADDR]]
// CHECK: %storeEnumTagSinglePayload = bitcast i8* [[WITNESS]] to void (%swift.opaque*, i32, i32, %swift.type*)*
// CHECK: call void %storeEnumTagSinglePayload(%swift.opaque* noalias [[OPAQUE_ENUM]], i32 0, i32 3, %swift.type* %T)
@@ -1256,7 +1256,7 @@ entry(%r : $*DynamicSinglePayload<T>, %t : $*T):
// CHECK: [[TMP:%.*]] = bitcast %swift.type* %T to i8***
// CHECK: [[TMP2:%.*]] = getelementptr inbounds i8**, i8*** [[TMP]], i{{.*}} -1
// CHECK: [[VWT:%.*]] = load i8**, i8*** [[TMP2]]
// CHECK: [[ENUMADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 8
// CHECK: [[ENUMADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 7
// CHECK: [[WITNESS:%.*]] = load i8*, i8** [[ENUMADDR]]
// CHECK: %storeEnumTagSinglePayload = bitcast i8* [[WITNESS]] to void (%swift.opaque*, i32, i32, %swift.type*)*
// CHECK: call void %storeEnumTagSinglePayload(%swift.opaque* noalias [[OPAQUE_ENUM]], i32 1, i32 3, %swift.type* %T)
@@ -2640,7 +2640,7 @@ entry(%x : $*MyOptional):
// CHECK: [[T_VWTS:%.*]] = bitcast %swift.type* [[T_CHECKED]] to i8***
// CHECK: [[T_VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[T_VWTS]], [[WORD]] -1
// CHECK: [[T_VWT:%.*]] = load i8**, i8*** [[T_VWT_ADDR]]
// CHECK: [[T_LAYOUT:%.*]] = getelementptr inbounds i8*, i8** [[T_VWT]], i32 9
// CHECK: [[T_LAYOUT:%.*]] = getelementptr inbounds i8*, i8** [[T_VWT]], i32 8
// CHECK: call void @swift_initEnumMetadataSingleCase(%swift.type* [[METADATA]], [[WORD]] 0, i8** [[T_LAYOUT]])
// CHECK: ret %swift.metadata_response
@@ -2659,7 +2659,7 @@ entry(%x : $*MyOptional):
// CHECK: [[T_VWTS:%.*]] = bitcast %swift.type* [[T_CHECKED]] to i8***
// CHECK: [[T_VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[T_VWTS]], [[WORD]] -1
// CHECK: [[T_VWT:%.*]] = load i8**, i8*** [[T_VWT_ADDR]]
// CHECK: [[T_LAYOUT:%.*]] = getelementptr inbounds i8*, i8** [[T_VWT]], i32 9
// CHECK: [[T_LAYOUT:%.*]] = getelementptr inbounds i8*, i8** [[T_VWT]], i32 8
// CHECK: call void @swift_initEnumMetadataSinglePayload(%swift.type* [[METADATA]], [[WORD]] 0, i8** [[T_LAYOUT]], i32 3)
// CHECK-64-LABEL: define linkonce_odr hidden void @"$S4enum17StructWithWeakVarVwxs"(%swift.opaque* noalias %dest, i32 %index, %swift.type* %StructWithWeakVar)

View File

@@ -433,7 +433,7 @@ entry(%a : $*EitherOr<T, C>, %b : $*EitherOr<T, C>):
// CHECK: [[T0:%.*]] = bitcast %swift.type* [[T_CHECKED]] to i8***
// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8**, i8*** [[T0]]
// CHECK-NEXT: [[VALUE_WITNESSES:%.*]] = load i8**, i8*** [[T1]]
// CHECK-NEXT: [[LAYOUT:%.*]] = getelementptr inbounds i8*, i8** [[VALUE_WITNESSES]], i32 9
// CHECK-NEXT: [[LAYOUT:%.*]] = getelementptr inbounds i8*, i8** [[VALUE_WITNESSES]], i32 8
// CHECK-NEXT: store i8** [[LAYOUT]], {{.*}} [[BUF0]]
// CHECK: [[BUF1:%.*]] = getelementptr {{.*}} [[BUF]], i32 0, i32 1
@@ -445,7 +445,7 @@ entry(%a : $*EitherOr<T, C>, %b : $*EitherOr<T, C>):
// CHECK: [[T0:%.*]] = bitcast %swift.type* [[U_CHECKED]] to i8***
// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8**, i8*** [[T0]]
// CHECK-NEXT: [[VALUE_WITNESSES:%.*]] = load i8**, i8*** [[T1]]
// CHECK-NEXT: [[LAYOUT:%.*]] = getelementptr inbounds i8*, i8** [[VALUE_WITNESSES]], i32 9
// CHECK-NEXT: [[LAYOUT:%.*]] = getelementptr inbounds i8*, i8** [[VALUE_WITNESSES]], i32 8
// CHECK-NEXT: store i8** [[LAYOUT]], {{.*}} [[BUF1]]
// CHECK: call void @swift_initEnumMetadataMultiPayload(%swift.type* [[METADATA]], {{i(32|64)}} 0, {{i(32|64)}} 2, i8*** [[BUF0]])

View File

@@ -119,7 +119,7 @@ public func constructResilientEnumNoPayload() -> Medium {
// CHECK-NEXT: [[VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[METADATA_ADDR]], [[INT]] -1
// CHECK-NEXT: [[VWT:%.*]] = load i8**, i8*** [[VWT_ADDR]]
// CHECK-NEXT: [[WITNESS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 17
// CHECK-NEXT: [[WITNESS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 16
// CHECK-NEXT: [[WITNESS:%.*]] = load i8*, i8** [[WITNESS_ADDR]]
// CHECK-NEXT: [[WITNESS_FN:%.*]] = bitcast i8* [[WITNESS]]
// CHECK-NEXT: call void [[WITNESS_FN]](%swift.opaque* noalias %0, i32 [[TAG]], %swift.type* [[METADATA]])
@@ -148,7 +148,7 @@ public func constructResilientEnumPayload(_ s: Size) -> Medium {
// CHECK-NEXT: [[VWT_ADDR2:%.*]] = getelementptr inbounds i8**, i8*** [[METADATA_ADDR2]], [[INT]] -1
// CHECK-NEXT: [[VWT2:%.*]] = load i8**, i8*** [[VWT_ADDR2]]
// CHECK-NEXT: [[WITNESS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT2]], i32 17
// CHECK-NEXT: [[WITNESS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT2]], i32 16
// CHECK-NEXT: [[WITNESS:%.*]] = load i8*, i8** [[WITNESS_ADDR]]
// CHECK-NEXT: [[WITNESS_FN:%destructiveInjectEnumTag]] = bitcast i8* [[WITNESS]]
// CHECK-NEXT: call void [[WITNESS_FN]](%swift.opaque* noalias %0, i32 [[TAG]], %swift.type* [[METADATA2]])
@@ -165,7 +165,7 @@ public func constructResilientEnumPayload(_ s: Size) -> Medium {
// CHECK: [[VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[METADATA_ADDR]], [[INT]] -1
// CHECK: [[VWT:%.*]] = load i8**, i8*** [[VWT_ADDR]]
// CHECK: [[WITNESS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 9
// CHECK: [[WITNESS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 8
// CHECK: [[WITNESS:%.*]] = load i8*, i8** [[WITNESS_ADDR]]
// CHECK: [[WITNESS_FOR_SIZE:%size]] = ptrtoint i8* [[WITNESS]]
// CHECK: [[ALLOCA:%.*]] = alloca i8, {{.*}} [[WITNESS_FOR_SIZE]], align 16
@@ -177,7 +177,7 @@ public func constructResilientEnumPayload(_ s: Size) -> Medium {
// CHECK: [[WITNESS_FN:%initializeWithCopy]] = bitcast i8* [[WITNESS]]
// CHECK: [[ENUM_COPY:%.*]] = call %swift.opaque* [[WITNESS_FN]](%swift.opaque* noalias [[ENUM_STORAGE]], %swift.opaque* noalias %0, %swift.type* [[METADATA]])
// CHECK: [[WITNESS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 15
// CHECK: [[WITNESS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 14
// CHECK: [[WITNESS:%.*]] = load i8*, i8** [[WITNESS_ADDR]]
// CHECK: [[WITNESS_FN:%getEnumTag]] = bitcast i8* [[WITNESS]]
// CHECK: [[TAG:%.*]] = call i32 [[WITNESS_FN]](%swift.opaque* noalias [[ENUM_STORAGE]], %swift.type* [[METADATA]])

View File

@@ -94,14 +94,13 @@ enum GenericFixedLayout<T> {
}
// CHECK-LABEL: @"$S20enum_value_semantics20SinglePayloadTrivialOWV" = internal constant [18 x i8*] [
// CHECK-LABEL: @"$S20enum_value_semantics20SinglePayloadTrivialOWV" = internal constant [17 x i8*] [
// CHECK: i8* bitcast (i8* (i8*, i8*, %swift.type*)* @__swift_memcpy9_8 to i8*),
// CHECK: i8* bitcast (void (i8*, %swift.type*)* @__swift_noop_void_return to i8*),
// CHECK: i8* bitcast (i8* (i8*, i8*, %swift.type*)* @__swift_memcpy9_8 to i8*),
// CHECK: i8* bitcast (i8* (i8*, i8*, %swift.type*)* @__swift_memcpy9_8 to i8*),
// CHECK: i8* bitcast (i8* (i8*, i8*, %swift.type*)* @__swift_memcpy9_8 to i8*),
// CHECK: i8* bitcast (i8* (i8*, i8*, %swift.type*)* @__swift_memcpy9_8 to i8*),
// CHECK: i8* bitcast (i8* (i8*, i8*, %swift.type*)* @__swift_memcpy9_8 to i8*),
// CHECK: i8* bitcast (i32 (%swift.opaque*, i32, %swift.type*)* @"$S20enum_value_semantics20SinglePayloadTrivialOwet" to i8*),
// CHECK: i8* bitcast (void (%swift.opaque*, i32, i32, %swift.type*)* @"$S20enum_value_semantics20SinglePayloadTrivialOwst" to i8*),
// CHECK: i8* inttoptr (i64 9 to i8*),
@@ -118,13 +117,13 @@ enum GenericFixedLayout<T> {
// CHECK-LABEL: @"$S20enum_value_semantics20SinglePayloadTrivialOMf" =
// CHECK-SAME: internal constant <{ {{.*}} }> <{
// CHECK-SAME: i8** getelementptr inbounds ([18 x i8*], [18 x i8*]* @"$S20enum_value_semantics20SinglePayloadTrivialOWV", i32 0, i32 0),
// CHECK-SAME: i8** getelementptr inbounds ([17 x i8*], [17 x i8*]* @"$S20enum_value_semantics20SinglePayloadTrivialOWV", i32 0, i32 0),
// CHECK-SAME: i64 2,
// CHECK-SAME: {{.*}}* @"$S20enum_value_semantics20SinglePayloadTrivialOMn"
// CHECK-SAME: }>
// CHECK-LABEL: @"$S20enum_value_semantics23SinglePayloadNontrivialOWV" = internal constant [18 x i8*] [
// CHECK-LABEL: @"$S20enum_value_semantics23SinglePayloadNontrivialOWV" = internal constant [17 x i8*] [
// CHECK: i8* bitcast (%swift.opaque* ([24 x i8]*, [24 x i8]*, %swift.type*)* @"$S20enum_value_semantics23SinglePayloadNontrivialOwCP" to i8*),
// CHECK: i8* bitcast (void (%swift.opaque*, %swift.type*)* @"$S20enum_value_semantics23SinglePayloadNontrivialOwxx" to i8*),
// CHECK: i8* bitcast (%swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* @"$S20enum_value_semantics23SinglePayloadNontrivialOwcp" to i8*),
@@ -148,7 +147,7 @@ enum GenericFixedLayout<T> {
// CHECK-LABEL: @"$S20enum_value_semantics23SinglePayloadNontrivialOMf" =
// CHECK-SAME: internal constant <{ {{.*}} }> <{
// CHECK-SAME: i8** getelementptr inbounds ([18 x i8*], [18 x i8*]* @"$S20enum_value_semantics23SinglePayloadNontrivialOWV", i32 0, i32 0),
// CHECK-SAME: i8** getelementptr inbounds ([17 x i8*], [17 x i8*]* @"$S20enum_value_semantics23SinglePayloadNontrivialOWV", i32 0, i32 0),
// CHECK-SAME: i64 2,
// CHECK-SAME: {{.*}}* @"$S20enum_value_semantics23SinglePayloadNontrivialOMn"
// CHECK-SAME: }>
@@ -166,7 +165,7 @@ enum GenericFixedLayout<T> {
// Pattern flags. 0x400000 == (MetadataKind::Enum << 21).
// CHECK-SAME: i32 4194304,
// Value witness table.
// CHECK-SAME: i32 trunc (i64 sub (i64 ptrtoint ([18 x i8*]* @"$S20enum_value_semantics18GenericFixedLayoutOWV" to i64), i64 ptrtoint (i32* getelementptr inbounds (<{ i32, i32, i32, i32 }>, <{ i32, i32, i32, i32 }>* @"$S20enum_value_semantics18GenericFixedLayoutOMP", i32 0, i32 3) to i64)) to i32)
// CHECK-SAME: i32 trunc (i64 sub (i64 ptrtoint ([17 x i8*]* @"$S20enum_value_semantics18GenericFixedLayoutOWV" to i64), i64 ptrtoint (i32* getelementptr inbounds (<{ i32, i32, i32, i32 }>, <{ i32, i32, i32, i32 }>* @"$S20enum_value_semantics18GenericFixedLayoutOMP", i32 0, i32 3) to i64)) to i32)
// CHECK-SAME: }>
sil @single_payload_nontrivial_copy_destroy : $(@owned SinglePayloadNontrivial) -> () {

View File

@@ -42,20 +42,11 @@ bb0(%0 : $*Any, %1 : $*Any):
// CHECK: call %Any* @"$SypWOb"(%Any* %1, %Any* %0)
// CHECK-NEXT: ret void
// CHECK-DAG: define linkonce_odr hidden %Any* @"$SypWOb"([[ANY:%Any]]*, %Any*)
// CHECK: [[T0:%.*]] = getelementptr inbounds [[ANY]], [[ANY]]* [[SRC:%0]], i32 0, i32 1
// CHECK-NEXT: [[TYPE:%.*]] = load %swift.type*, %swift.type** [[T0]], align 8
// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[ANY]], [[ANY]]* [[DEST:%1]], i32 0, i32 1
// CHECK-NEXT: store %swift.type* [[TYPE]], %swift.type** [[T0]], align 8
// CHECK-NEXT: [[FROM_BUFFER_ADDR:%.*]] = getelementptr inbounds %Any, %Any* %0, i32 0, i32 0
// CHECK-NEXT: [[TO_BUFFER_ADDR:%.*]] = getelementptr inbounds %Any, %Any* %1, i32 0, i32 0
// CHECK-NEXT: [[CAST:%.*]] = bitcast %swift.type* [[TYPE]] to i8***
// CHECK-NEXT: [[VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[CAST]], i64 -1
// CHECK-NEXT: [[VWT:%.*]] = load i8**, i8*** [[VWT_ADDR]]
// CHECK-NEXT: [[VW_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 6
// CHECK-NEXT: [[VW:%.*]] = load i8*, i8** [[VW_ADDR]]
// CHECK-NEXT: [[INITWITHTAKEBUFFER:%.*]] = bitcast i8* [[VW]]
// CHECK-NEXT: call %swift.opaque* [[INITWITHTAKEBUFFER]]({{.*}} [[TO_BUFFER_ADDR]], {{.*}} [[FROM_BUFFER_ADDR]], %swift.type* [[TYPE]])
// CHECK-DAG: define linkonce_odr hidden %Any* @"$SypWOb"(%Any*, %Any*)
// CHECK: %2 = bitcast %Any* %1 to i8*
// CHECK-NEXT: %3 = bitcast %Any* %0 to i8*
// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %2, i8* %3, i64 32, i32 8, i1 false)
// CHECK-NEXT: ret %Any* %1
// rdar://problem/19035529
@objc protocol OP {}

View File

@@ -41,7 +41,7 @@ entry(%0 : $*T):
// CHECK: [[CAST:%.*]] = bitcast %swift.type* [[METATYPE]]
// CHECK: [[VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[CAST]], {{(i64|i32)}} -1
// CHECK: [[VWT:%.*]] = load i8**, i8*** [[VWT_ADDR]]
// CHECK: [[FLAG_WITNESS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 10
// CHECK: [[FLAG_WITNESS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 9
// CHECK: [[FLAG_WITNESS:%.*]] = load i8*, i8** [[FLAG_WITNESS_ADDR]]
// CHECK: [[FLAGS:%.*]] = ptrtoint i8* [[FLAG_WITNESS]]
// CHECK: [[ISNOTINLINE:%.*]] = and {{(i64|i32)}} [[FLAGS]], 131072
@@ -115,7 +115,7 @@ entry:
// CHECK: [[CAST:%.*]] = bitcast %swift.type* [[META]] to i8***
// CHECK: [[VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** %3, {{(i64|i32)}} -1
// CHECK: [[VWT:%.*]] = load i8**, i8*** [[VWT_ADDR]]
// CHECK: [[VW_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 10
// CHECK: [[VW_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 9
// CHECK: [[VW:%.*]] = load i8*, i8** [[VW_ADDR]]
// CHECK: [[FLAGS:%.*]] = ptrtoint i8* [[VW]] to {{(i64|i32)}}
// CHECK: [[MASKED:%.*]] = and {{(i64|i32)}} [[FLAGS]], 131072
@@ -132,7 +132,7 @@ entry:
// CHECK: [[CAST:%.*]] = bitcast %swift.type* [[META]] to i8***
// CHECK: [[VWT_ADDR2:%.*]] = getelementptr inbounds i8**, i8*** [[CAST]], {{(i64|i32)}} -1
// CHECK: [[VWT2:%.*]] = load i8**, i8*** [[VWT_ADDR2]]
// CHECK: [[VW_ADDR2:%.*]] = getelementptr inbounds i8*, i8** [[VWT2]], i32 9
// CHECK: [[VW_ADDR2:%.*]] = getelementptr inbounds i8*, i8** [[VWT2]], i32 8
// CHECK: [[VW2:%.*]] = load i8*, i8** [[VW_ADDR2]]
// CHECK: [[SIZE:%.*]] = ptrtoint i8* [[VW2]] to {{(i64|i32)}}
// CHECK: [[ALIGNMASK:%.*]] = and {{(i64|i32)}} [[FLAGS]], 65535
@@ -164,7 +164,7 @@ bb0(%0 : $*Existential):
// CHECK: [[CAST:%.*]] = bitcast %swift.type* %1 to i8***
// CHECK: [[VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[CAST]], {{(i64|i32)}} -1
// CHECK: [[VWT:%.*]] = load i8**, i8*** [[VWT_ADDR]]
// CHECK: [[VW_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 10
// CHECK: [[VW_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 9
// CHECK: [[VW:%.*]] = load i8*, i8** [[VW_ADDR]]
// CHECK: [[FLAGS:%.*]] = ptrtoint i8* [[VW]] to {{(i64|i32)}}
// CHECK: [[ISNOTINLINE:%.*]] = and {{(i64|i32)}} [[FLAGS]], 131072
@@ -207,7 +207,7 @@ bb0(%0 : $*Existential):
// CHECK: [[CAST:%.*]] = bitcast %swift.type* %1 to i8***
// CHECK: [[VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[CAST]], {{(i64|i32)}} -1
// CHECK: [[VWT:%.*]] = load i8**, i8*** [[VWT_ADDR]]
// CHECK: [[VW_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 10
// CHECK: [[VW_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 9
// CHECK: [[VW:%.*]] = load i8*, i8** [[VW_ADDR]]
// CHECK: [[FLAGS:%.*]] = ptrtoint i8* [[VW]] to {{(i64|i32)}}
// CHECK: [[ISNOTINLINE:%.*]] = and {{(i64|i32)}} [[FLAGS]], 131072
@@ -244,7 +244,7 @@ bb0(%0 : $*Existential):
// CHECK: [[CAST:%.*]] = bitcast %swift.type* [[METADATA]] to i8***
// CHECK: [[VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[CAST]], {{(i64|i32)}} -1
// CHECK: [[VWT:%.*]] = load i8**, i8*** [[VWT_ADDR]]
// CHECK: [[VW_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 10
// CHECK: [[VW_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 9
// CHECK: [[VW:%.*]] = load i8*, i8** [[VW_ADDR]]
// CHECK: [[FLAGS:%.*]] = ptrtoint i8* [[VW]] to {{(i64|i32)}}
// CHECK: [[ISNOTINLINE:%.*]] = and {{(i64|i32)}} [[FLAGS]], 131072
@@ -301,7 +301,7 @@ bb0(%0 : $*Existential):
// CHECK: [[CAST:%.*]] = bitcast %swift.type* [[DEST_TYPE]] to i8***
// CHECK: [[VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[CAST]], {{(i64|i32)}} -1
// CHECK: [[VWT:%.*]] = load i8**, i8*** [[VWT_ADDR]]
// CHECK: [[VW_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 10
// CHECK: [[VW_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 9
// CHECK: [[VW:%.*]] = load i8*, i8** [[VW_ADDR]]
// CHECK: [[FLAGS:%.*]] = ptrtoint i8* [[VW]] to {{(i64|i32)}}
// CHECK: [[MASKED:%.*]] = and {{(i64|i32)}} [[FLAGS]], 131072
@@ -339,7 +339,7 @@ bb0(%0 : $*Existential):
// CHECK: [[CAST:%.*]] = bitcast %swift.type* [[DEST_TYPE]] to i8***
// CHECK: [[DEST_VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[CAST]], {{(i64|i32)}} -1
// CHECK: [[DEST_VWT:%.*]] = load i8**, i8*** [[DEST_VWT_ADDR]]
// CHECK: [[DEST_VW_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[DEST_VWT]], i32 10
// CHECK: [[DEST_VW_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[DEST_VWT]], i32 9
// CHECK: [[DEST_VW:%.*]] = load i8*, i8** [[DEST_VW_ADDR]]
// CHECK: [[DEST_FLAGS:%.*]] = ptrtoint i8* [[DEST_VW]] to {{(i64|i32)}}
// CHECK: [[DEST_ISNOTINLINE:%.*]] = and {{(i64|i32)}} [[DEST_FLAGS]], 131072
@@ -347,7 +347,7 @@ bb0(%0 : $*Existential):
// CHECK: [[CAST:%.*]] = bitcast %swift.type* [[SRC_TYPE]] to i8***
// CHECK: [[SRC_VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[CAST]], {{(i64|i32)}} -1
// CHECK: [[SRC_VWT:%.*]] = load i8**, i8*** [[SRC_VWT_ADDR]]
// CHECK: [[SRC_VW_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[SRC_VWT]], i32 10
// CHECK: [[SRC_VW_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[SRC_VWT]], i32 9
// CHECK: [[SRC_VW:%.*]] = load i8*, i8** [[SRC_VW_ADDR]]
// CHECK: [[SRC_FLAGS:%.*]] = ptrtoint i8* [[SRC_VW]] to {{(i64|i32)}}
// CHECK: [[SRC_ISNOTINLINE:%.*]] = and {{(i64|i32)}} [[SRC_FLAGS]], 131072
@@ -443,24 +443,10 @@ bb0(%0 : $*Existential):
return %t : $()
}
// CHECK: define linkonce_odr hidden %T25existentials_opaque_boxed11ExistentialP* @"$S25existentials_opaque_boxed11Existential_pWOb"(%T25existentials_opaque_boxed11ExistentialP*, %T25existentials_opaque_boxed11ExistentialP*)
// CHECK: [[METADATA_ADDR:%.*]] = getelementptr inbounds %T25existentials_opaque_boxed11ExistentialP, %T25existentials_opaque_boxed11ExistentialP* %0, i32 0, i32 1
// CHECK: [[METADATA:%.*]] = load %swift.type*, %swift.type** [[METADATA_ADDR]]
// CHECK: [[LOCAL_METADATA_ADDR:%.*]] = getelementptr inbounds %T25existentials_opaque_boxed11ExistentialP, %T25existentials_opaque_boxed11ExistentialP* %1, i32 0, i32 1
// CHECK: store %swift.type* [[METADATA]], %swift.type** [[LOCAL_METADATA_ADDR]]
// CHECK: [[PWT_ADDR:%.*]] = getelementptr inbounds %T25existentials_opaque_boxed11ExistentialP, %T25existentials_opaque_boxed11ExistentialP* %0, i32 0, i32 2
// CHECK: [[PWT:%.*]] = load i8**, i8*** [[PWT_ADDR]]
// CHECK: [[LOCAL_PWT_ADDR:%.*]] = getelementptr inbounds %T25existentials_opaque_boxed11ExistentialP, %T25existentials_opaque_boxed11ExistentialP* %1, i32 0, i32 2
// CHECK: store i8** [[PWT]], i8*** [[LOCAL_PWT_ADDR]]
// CHECK: [[BUFFER_ARG_ADDR:%.*]] = getelementptr inbounds %T25existentials_opaque_boxed11ExistentialP, %T25existentials_opaque_boxed11ExistentialP* %0, i32 0, i32 0
// CHECK: [[BUFFER_LOCAL_ADDR:%.*]] = getelementptr inbounds %T25existentials_opaque_boxed11ExistentialP, %T25existentials_opaque_boxed11ExistentialP* %1, i32 0, i32 0
// CHECK: [[CAST_ADDR:%.*]] = bitcast %swift.type* [[METADATA]] to i8***
// CHECK: [[VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[CAST_ADDR]], {{(i64|i32)}} -1
// CHECK: [[VWT:%.*]] = load i8**, i8*** [[VWT_ADDR]]
// CHECK: [[VW_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 6
// CHECK: [[VW:%.*]] = load i8*, i8** [[VW_ADDR]]
// CHECK: [[INITWITHTAKEBUFFER:%.*]] = bitcast i8* [[VW]]
// CHECK: call %swift.opaque* [[INITWITHTAKEBUFFER]]({{.*}} [[BUFFER_LOCAL_ADDR]], {{.*}} [[BUFFER_ARG_ADDR]], %swift.type* [[METADATA]])
// CHECK-LABEL: define linkonce_odr hidden %T25existentials_opaque_boxed11ExistentialP* @"$S25existentials_opaque_boxed11Existential_pWOb"(%T25existentials_opaque_boxed11ExistentialP*, %T25existentials_opaque_boxed11ExistentialP*)
// CHECK: %2 = bitcast %T25existentials_opaque_boxed11ExistentialP* %1 to i8*
// CHECK: %3 = bitcast %T25existentials_opaque_boxed11ExistentialP* %0 to i8*
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %2, i8* %3, i64 40, i32 8, i1 false)
// CHECK: ret %T25existentials_opaque_boxed11ExistentialP* %1
// CHECK: define{{( dllexport)?}}{{( protected)?}} swiftcc void @test_initWithTake_existential_addr(%T25existentials_opaque_boxed11ExistentialP*

View File

@@ -38,7 +38,7 @@ func allToInt<T>(_ x: T) -> Int {
// CHECK: [[TYPE_ADDR:%.*]] = bitcast %swift.type* %T to i8***
// CHECK: [[VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[TYPE_ADDR]], i64 -1
// CHECK: [[VWT:%.*]] = load i8**, i8*** [[VWT_ADDR]]
// CHECK: [[SIZE_WITNESS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 9
// CHECK: [[SIZE_WITNESS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 8
// CHECK: [[SIZE_WITNESS:%.*]] = load i8*, i8** [[SIZE_WITNESS_ADDR]]
// CHECK: [[SIZE:%.*]] = ptrtoint i8* [[SIZE_WITNESS]]
// CHECK: [[T_ALLOCA:%.*]] = alloca i8, {{.*}} [[SIZE]], align 16

View File

@@ -389,7 +389,7 @@ entry(%c : $RootGeneric<Int32>):
// CHECK: [[T0:%.*]] = bitcast %swift.type* [[B_CHECKED]] to i8***
// CHECK: [[T1:%.*]] = getelementptr inbounds i8**, i8*** [[T0]], i64 -1
// CHECK: [[VWT:%.*]] = load i8**, i8*** [[T1]], align 8
// CHECK: [[T0:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 9
// CHECK: [[T0:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 8
// CHECK: [[T1:%.*]] = getelementptr inbounds i8**, i8*** [[FIELDS_ADDR]], i32 0
// CHECK: store i8** [[T0]], i8*** [[T1]], align 8
// CHECK: call void @swift_initClassMetadata(%swift.type* [[METADATA]], i64 0, i64 1, i8*** [[FIELDS_ADDR]], i64* [[OFFSETS]])

View File

@@ -228,20 +228,6 @@ entry(%0 : $*ComplexDynamic<A, B>, %1 : $*Byteful, %2 : $*A, %3 : $*B, %4 : $*Ch
// CHECK-NEXT: ret %swift.opaque* [[T2]]
// initializeBufferWithTakeOfBuffer
// CHECK-LABEL: define linkonce_odr hidden %swift.opaque* @"$S15generic_structs13SingleDynamicVwTK"([24 x i8]* noalias %dest, [24 x i8]* noalias %src, %swift.type* %"SingleDynamic<T>") {{.*}} {
// CHECK: %T = load %swift.type*,
// CHECK-NEXT: [[T0:%.*]] = bitcast %swift.type* %T to i8***
// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8**, i8*** [[T0]], i64 -1
// CHECK-NEXT: %T.valueWitnesses = load i8**, i8*** [[T1]]
// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds i8*, i8** %T.valueWitnesses, i32 6
// CHECK-NEXT: [[T1:%.*]] = load i8*, i8** [[T0]],
// CHECK-NEXT: [[FN:%.*]] = bitcast i8* [[T1]] to %swift.opaque* ([24 x i8]*, [24 x i8]*, %swift.type*)*
// CHECK-NEXT: [[T0:%.*]] = call %swift.opaque* [[FN]]([24 x i8]* noalias %dest, [24 x i8]* noalias %src, %swift.type* %T)
// CHECK-NEXT: [[T1:%.*]] = bitcast %swift.opaque* [[T0]] to {{.*}}
// CHECK-NEXT: [[T2:%.*]] = bitcast {{.*}} [[T1]] to %swift.opaque*
// CHECK-NEXT: ret %swift.opaque* [[T2]]
protocol HasAssociatedType {
associatedtype Assoc
}

View File

@@ -18,7 +18,7 @@ func dup<T>(_ x: T) -> (T, T) { var x = x; return (x,x) }
// CHECK: [[TYPE_ADDR:%.*]] = bitcast %swift.type* %T to i8***
// CHECK: [[VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[TYPE_ADDR]], i64 -1
// CHECK: [[VWT:%.*]] = load i8**, i8*** [[VWT_ADDR]]
// CHECK: [[SIZE_WITNESS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 9
// CHECK: [[SIZE_WITNESS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 8
// CHECK: [[SIZE_WITNESS:%.*]] = load i8*, i8** [[SIZE_WITNESS_ADDR]]
// CHECK: [[SIZE:%.*]] = ptrtoint i8* [[SIZE_WITNESS]]
// CHECK: [[X_ALLOCA:%.*]] = alloca i8, {{.*}} [[SIZE]], align 16

View File

@@ -125,7 +125,7 @@ bb0:
// CHECK: [[CAST:%.*]] = bitcast %swift.type* %0 to i8***
// CHECK: [[VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[CAST]], {{.*}} -1
// CHECK: [[VWT:%.*]] = load i8**, i8*** [[VWT_ADDR]]
// CHECK: [[FLAGS_ADDR:%.*]] = getelementptr inbounds i8*, i8** %.valueWitnesses, i32 10
// CHECK: [[FLAGS_ADDR:%.*]] = getelementptr inbounds i8*, i8** %.valueWitnesses, i32 9
// CHECK: [[FLAGSWITNESS:%.*]] = load i8*, i8** [[FLAGS_ADDR]]
// CHECK: [[FLAGS:%.*]] = ptrtoint i8* [[FLAGSWITNESS]] to i{{.*}}
// CHECK: [[ISNOTINLINE:%.*]] = and {{.*}} [[FLAGS]], 131072
@@ -136,7 +136,7 @@ bb0:
// CHECK: [[CAST:%.*]] = bitcast %swift.type* %0 to i8***
// CHECK: [[VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[CAST]], {{.*}} -1
// CHECK: [[VWT:%.*]] = load i8**, i8*** [[VWT_ADDR]]
// CHECK: [[SIZE_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 9
// CHECK: [[SIZE_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 8
// CHECK: [[SIZEWITNESS:%.*]] = load i8*, i8** [[SIZE_ADDR]]
// CHECK: [[SIZE:%.*]] = ptrtoint i8* [[SIZEWITNESS]]
// CHECK: [[ALIGN:%.*]] = and {{.*}} [[FLAGS]], 65535
@@ -155,7 +155,7 @@ bb0:
// CHECK: [[CAST:%.*]] = bitcast %swift.type* %0 to i8***
// CHECK: [[VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[CAST]], {{.*}} -1
// CHECK: [[VWT:%.*]] = load i8**, i8*** [[VWT_ADDR]]
// CHECK: [[FLAGS_ADDR:%.*]] = getelementptr inbounds i8*, i8** %.valueWitnesses, i32 10
// CHECK: [[FLAGS_ADDR:%.*]] = getelementptr inbounds i8*, i8** %.valueWitnesses, i32 9
// CHECK: [[FLAGSWITNESS:%.*]] = load i8*, i8** [[FLAGS_ADDR]]
// CHECK: [[FLAGS:%.*]] = ptrtoint i8* [[FLAGSWITNESS]] to i{{.*}}
// CHECK: [[ISNOTINLINE:%.*]] = and {{.*}} [[FLAGS]], 131072

View File

@@ -45,7 +45,7 @@ entry(%p : $*(), %i: $Builtin.Word):
// CHECK: %3 = bitcast %swift.type* %T to i8***
// CHECK-NEXT: %4 = getelementptr inbounds i8**, i8*** %3, i64 -1
// CHECK-NEXT: %T.valueWitnesses = load i8**, i8*** %4, align 8
// CHECK-NEXT: %5 = getelementptr inbounds i8*, i8** %T.valueWitnesses, i32 11
// CHECK-NEXT: %5 = getelementptr inbounds i8*, i8** %T.valueWitnesses, i32 10
// CHECK-NEXT: %6 = load i8*, i8** %5, align 8
// CHECK-NEXT: %stride = ptrtoint i8* %6 to i64
// CHECK-NEXT: %7 = mul nsw i64 %1, %stride

View File

@@ -22,7 +22,7 @@ bb0(%x : $*T):
// CHECK: [[TYPE_ADDR:%.*]] = bitcast %swift.type* %T to i8***
// CHECK-NEXT: [[VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[TYPE_ADDR]], {{(i32|i64)}} -1
// CHECK-NEXT: [[VWT:%.*]] = load i8**, i8*** [[VWT_ADDR]]
// CHECK-NEXT: [[SIZE_WITNESS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 9
// CHECK-NEXT: [[SIZE_WITNESS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 8
// CHECK-NEXT: [[SIZE_WITNESS:%.*]] = load i8*, i8** [[SIZE_WITNESS_ADDR]]
// CHECK-NEXT: [[SIZE:%.*]] = ptrtoint i8* [[SIZE_WITNESS]]
// CHECK-NEXT: [[Y_ALLOCA:%.*]] = alloca i8, {{.*}} [[SIZE]], align 16
@@ -61,7 +61,7 @@ bb0(%x : $*T):
// CHECK: [[TYPE_ADDR:%.*]] = bitcast %swift.type* %T to i8***
// CHECK-NEXT: [[VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[TYPE_ADDR]], {{(i32|i64)}} -1
// CHECK-NEXT: [[VWT:%.*]] = load i8**, i8*** [[VWT_ADDR]]
// CHECK-NEXT: [[SIZE_WITNESS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 9
// CHECK-NEXT: [[SIZE_WITNESS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 8
// CHECK-NEXT: [[SIZE_WITNESS:%.*]] = load i8*, i8** [[SIZE_WITNESS_ADDR]]
// CHECK-NEXT: [[SIZE:%.*]] = ptrtoint i8* [[SIZE_WITNESS]]
// CHECK-NEXT: [[Y_ALLOCA:%.*]] = alloca i8, {{.*}} [[SIZE]], align 16

View File

@@ -16,7 +16,7 @@
// CHECK: [[METADATA:%.*]] = extractvalue %swift.metadata_response [[T0]], 0
// CHECK: [[VWT:%.*]] = load i8**,
// Allocate 'copy'.
// CHECK: [[T0:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 9
// CHECK: [[T0:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 8
// CHECK: [[T1:%.*]] = load i8*, i8** [[T0]],
// CHECK: [[SIZE:%.*]] = ptrtoint i8* [[T1]] to [[INT]]
// CHECK: [[ALLOCA:%.*]] = alloca i8, [[INT]] [[SIZE]],

View File

@@ -20,7 +20,7 @@ import OtherModule
// CHECK: [[METADATA:%.*]] = extractvalue %swift.metadata_response [[T0]], 0
// CHECK: [[VWT:%.*]] = load i8**,
// Allocate 'copy'.
// CHECK: [[T0:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 9
// CHECK: [[T0:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 8
// CHECK: [[T1:%.*]] = load i8*, i8** [[T0]],
// CHECK: [[SIZE:%.*]] = ptrtoint i8* [[T1]] to [[INT]]
// CHECK: [[ALLOCA:%.*]] = alloca i8, [[INT]] [[SIZE]],
@@ -49,7 +49,7 @@ public func copyFoo(foo: Foo) -> Foo {
// CHECK: [[METADATA:%.*]] = extractvalue %swift.metadata_response [[T0]], 0
// CHECK: [[VWT:%.*]] = load i8**,
// Allocate 'copy'.
// CHECK: [[T0:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 9
// CHECK: [[T0:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 8
// CHECK: [[T1:%.*]] = load i8*, i8** [[T0]],
// CHECK: [[SIZE:%.*]] = ptrtoint i8* [[T1]] to [[INT]]
// CHECK: [[ALLOCA:%.*]] = alloca i8, [[INT]] [[SIZE]],

View File

@@ -233,7 +233,7 @@ sil public_external @captured_fixed_and_dependent_params : $@convention(thin) <A
// CHECK: [[T_METADATA_BASE:%.*]] = bitcast %swift.type* %T to i8***
// CHECK: [[T_VWTABLE_ADDR:%.*]] = getelementptr {{.*}} [[T_METADATA_BASE]], [[WORD:i[0-9]+]] -1
// CHECK: [[T_VWTABLE:%.*]] = load {{.*}} [[T_VWTABLE_ADDR]]
// CHECK: [[T_FLAGS_ADDR:%.*]] = getelementptr {{.*}} [[T_VWTABLE]], i32 10
// CHECK: [[T_FLAGS_ADDR:%.*]] = getelementptr {{.*}} [[T_VWTABLE]], i32 9
// CHECK: [[T_FLAGS_PTR:%.*]] = load {{.*}} [[T_FLAGS_ADDR]]
// CHECK: [[T_FLAGS:%.*]] = ptrtoint {{.*}} [[T_FLAGS_PTR]] to [[WORD]]
// CHECK: [[T_ALIGN_MASK:%.*]] = and [[WORD]] [[T_FLAGS]], 65535
@@ -245,7 +245,7 @@ sil public_external @captured_fixed_and_dependent_params : $@convention(thin) <A
// CHECK: [[T_OFFSET:%.*]] = and [[WORD]] [[T_UP_TO_ALIGN_1]], [[T_ALIGN_MASK_NOT]]
// -- Add the size of T to start the Int field.
// CHECK: [[T_SIZE_ADDR:%.*]] = getelementptr {{.*}} [[T_VWTABLE]], i32 9
// CHECK: [[T_SIZE_ADDR:%.*]] = getelementptr {{.*}} [[T_VWTABLE]], i32 8
// CHECK: [[T_SIZE_PTR:%.*]] = load {{.*}} [[T_SIZE_ADDR]]
// CHECK: [[T_SIZE:%.*]] = ptrtoint {{.*}} [[T_SIZE_PTR]] to [[WORD]]
// CHECK: [[T_END:%.*]] = add [[WORD]] [[T_OFFSET]], [[T_SIZE]]

View File

@@ -25,7 +25,7 @@ public func functionWithResilientTypesSize(_ s: __owned Size, f: (__owned Size)
// CHECK: [[VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[METADATA_ADDR]], [[INT]] -1
// CHECK: [[VWT:%.*]] = load i8**, i8*** [[VWT_ADDR]]
// CHECK-NEXT: [[WITNESS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 9
// CHECK-NEXT: [[WITNESS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 8
// CHECK: [[WITNESS:%.*]] = load i8*, i8** [[WITNESS_ADDR]]
// CHECK: [[WITNESS_FOR_SIZE:%.*]] = ptrtoint i8* [[WITNESS]]
// CHECK: [[ALLOCA:%.*]] = alloca i8, {{.*}} [[WITNESS_FOR_SIZE]], align 16

View File

@@ -34,14 +34,14 @@ struct TypeLayoutTest<T> {
// CHECK: [[T0:%.*]] = bitcast %swift.type* [[T_CHECKED]] to i8***
// CHECK: [[T1:%.*]] = getelementptr inbounds i8**, i8*** [[T0]], {{i32|i64}} -1
// CHECK: [[T_VALUE_WITNESSES:%.*]] = load i8**, i8*** [[T1]]
// CHECK: [[T_LAYOUT:%.*]] = getelementptr inbounds i8*, i8** [[T_VALUE_WITNESSES]], i32 9
// CHECK: [[T_LAYOUT:%.*]] = getelementptr inbounds i8*, i8** [[T_VALUE_WITNESSES]], i32 8
// CHECK: store i8** [[T_LAYOUT]]
var z: T
// -- native class, use standard NativeObject value witness
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBoWV", i32 9)
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBoWV", i32 8)
var a: C
// -- Single-element struct, shares layout of its field (Builtin.Int64)
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBi64_WV", i32 9)
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBi64_WV", i32 8)
var c: SSing
// -- Multi-element structs use open-coded layouts
// CHECK: store i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @type_layout_16_8_0_pod, i32 0, i32 0)
@@ -53,13 +53,13 @@ struct TypeLayoutTest<T> {
// CHECK-32: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_8_4_[[REF_XI]]_bt, i32 0, i32 0)
var f: SMult3
// -- Single-case enum, shares layout of its field (Builtin.Int64)
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBi64_WV", i32 9)
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBi64_WV", i32 8)
var g: ESing
// -- Multi-case enum, open-coded layout
// CHECK: store i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @type_layout_9_8_0_pod, i32 0, i32 0)
var h: EMult
// -- Single-element generic struct, shares layout of its field (T)
// CHECK: [[T_LAYOUT:%.*]] = getelementptr inbounds i8*, i8** [[T_VALUE_WITNESSES]], i32 9
// CHECK: [[T_LAYOUT:%.*]] = getelementptr inbounds i8*, i8** [[T_VALUE_WITNESSES]], i32 8
// CHECK: store i8** [[T_LAYOUT]]
var i: GSing<T>
// -- Multi-element generic struct, need to derive from metadata
@@ -71,13 +71,13 @@ struct TypeLayoutTest<T> {
// CHECK: [[T0:%.*]] = bitcast %swift.type* [[METADATA]] to i8***
// CHECK: [[T1:%.*]] = getelementptr inbounds i8**, i8*** [[T0]], {{i32|i64}} -1
// CHECK: [[VALUE_WITNESSES:%.*]] = load i8**, i8*** [[T1]]
// CHECK: [[LAYOUT:%.*]] = getelementptr inbounds i8*, i8** [[VALUE_WITNESSES]], i32 9
// CHECK: [[LAYOUT:%.*]] = getelementptr inbounds i8*, i8** [[VALUE_WITNESSES]], i32 8
// CHECK: store i8** [[LAYOUT]]
var j: GMult<T>
// -- Common layout, reuse common value witness table layout
// CHECK: store i8** getelementptr (i8*, i8** @"$SBi32_WV", i32 9)
// CHECK: store i8** getelementptr (i8*, i8** @"$SBi32_WV", i32 8)
var k: CommonLayout
// -- Single-field aggregate with alignment
// CHECK: store i8** getelementptr (i8*, i8** @"$SBi128_WV", i32 9)
// CHECK: store i8** getelementptr (i8*, i8** @"$SBi128_WV", i32 8)
var l: AlignedFourInts
}

View File

@@ -33,17 +33,17 @@ struct TypeLayoutTest<T> {
// CHECK: [[T0:%.*]] = bitcast %swift.type* [[T_CHECKED]] to i8***
// CHECK: [[T1:%.*]] = getelementptr inbounds i8**, i8*** [[T0]], {{i32|i64}} -1
// CHECK: [[T_VALUE_WITNESSES:%.*]] = load i8**, i8*** [[T1]]
// CHECK: [[T_LAYOUT:%.*]] = getelementptr inbounds i8*, i8** [[T_VALUE_WITNESSES]], i32 9
// CHECK: [[T_LAYOUT:%.*]] = getelementptr inbounds i8*, i8** [[T_VALUE_WITNESSES]], i32 8
// CHECK: store i8** [[T_LAYOUT]]
var z: T
// -- native class, use standard NativeObject value witness
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBoWV", i32 9)
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBoWV", i32 8)
var a: C
// -- ObjC class, use standard UnknownObject value witness
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBOWV", i32 9)
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBOWV", i32 8)
var b: O
// -- Single-element struct, shares layout of its field (Builtin.Int64)
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBi64_WV", i32 9)
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBi64_WV", i32 8)
var c: SSing
// -- Multi-element structs use open-coded layouts
// CHECK: store i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @type_layout_16_8_0_pod, i32 0, i32 0)
@@ -55,13 +55,13 @@ struct TypeLayoutTest<T> {
// CHECK-32: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_8_4_1000_bt, i32 0, i32 0)
var f: SMult3
// -- Single-case enum, shares layout of its field (Builtin.Int64)
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBi64_WV", i32 9)
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBi64_WV", i32 8)
var g: ESing
// -- Multi-case enum, open-coded layout
// CHECK: store i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @type_layout_9_8_0_pod, i32 0, i32 0)
var h: EMult
// -- Single-element generic struct, shares layout of its field (T)
// CHECK: [[T_LAYOUT:%.*]] = getelementptr inbounds i8*, i8** [[T_VALUE_WITNESSES]], i32 9
// CHECK: [[T_LAYOUT:%.*]] = getelementptr inbounds i8*, i8** [[T_VALUE_WITNESSES]], i32 8
// CHECK: store i8** [[T_LAYOUT]]
var i: GSing<T>
// -- Multi-element generic struct, need to derive from metadata
@@ -73,10 +73,10 @@ struct TypeLayoutTest<T> {
// CHECK: [[T0:%.*]] = bitcast %swift.type* [[METADATA]] to i8***
// CHECK: [[T1:%.*]] = getelementptr inbounds i8**, i8*** [[T0]], {{i32|i64}} -1
// CHECK: [[VALUE_WITNESSES:%.*]] = load i8**, i8*** [[T1]]
// CHECK: [[LAYOUT:%.*]] = getelementptr inbounds i8*, i8** [[VALUE_WITNESSES]], i32 9
// CHECK: [[LAYOUT:%.*]] = getelementptr inbounds i8*, i8** [[VALUE_WITNESSES]], i32 8
// CHECK: store i8** [[LAYOUT]]
var j: GMult<T>
// -- Common layout, reuse common value witness table layout
// CHECK: store i8** getelementptr (i8*, i8** @"$SBi32_WV", i32 9)
// CHECK: store i8** getelementptr (i8*, i8** @"$SBi32_WV", i32 8)
var k: CommonLayout
}

View File

@@ -10,23 +10,23 @@ struct ReferenceStorageTypeLayout<T, Native : C, Unknown : AnyObject> {
var z: T
// -- Known-Swift-refcounted type
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBoXoWV", i32 9)
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBoXoWV", i32 8)
unowned(safe) var cs: C
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBomWV", i32 9)
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBomWV", i32 8)
unowned(unsafe) var cu: C
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBoSgXwWV", i32 9)
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBoSgXwWV", i32 8)
weak var cwo: C?
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBoSgXwWV", i32 9)
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBoSgXwWV", i32 8)
weak var cwi: C!
// -- Known-Swift-refcounted archetype
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBoXoWV", i32 9)
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBoXoWV", i32 8)
unowned(safe) var nc: Native
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBomWV", i32 9)
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBomWV", i32 8)
unowned(unsafe) var nu: Native
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBoSgXwWV", i32 9)
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBoSgXwWV", i32 8)
weak var nwo: Native?
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBoSgXwWV", i32 9)
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBoSgXwWV", i32 8)
weak var nwi: Native!
// -- Open-code layout for protocol types with witness tables.
@@ -72,23 +72,23 @@ struct ReferenceStorageTypeLayout<T, Native : C, Unknown : AnyObject> {
weak var pqcwi: (P & Q & C)!
// -- Unknown-refcounted existential without witness tables.
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$S[[UNKNOWN:B[Oo]]]XoWV", i32 9)
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$S[[UNKNOWN:B[Oo]]]XoWV", i32 8)
unowned(safe) var aos: AnyObject
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBomWV", i32 9)
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBomWV", i32 8)
unowned(unsafe) var aou: AnyObject
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$S[[UNKNOWN]]SgXwWV", i32 9)
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$S[[UNKNOWN]]SgXwWV", i32 8)
weak var aowo: AnyObject?
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$S[[UNKNOWN]]SgXwWV", i32 9)
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$S[[UNKNOWN]]SgXwWV", i32 8)
weak var aowi: AnyObject!
// -- Unknown-refcounted archetype
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$S[[UNKNOWN:B[Oo]]]XoWV", i32 9)
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$S[[UNKNOWN:B[Oo]]]XoWV", i32 8)
unowned(safe) var us: Unknown
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBomWV", i32 9)
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBomWV", i32 8)
unowned(unsafe) var uu: Unknown
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$S[[UNKNOWN]]SgXwWV", i32 9)
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$S[[UNKNOWN]]SgXwWV", i32 8)
weak var uwo: Unknown?
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$S[[UNKNOWN]]SgXwWV", i32 9)
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$S[[UNKNOWN]]SgXwWV", i32 8)
weak var uwi: Unknown!
}

View File

@@ -15,52 +15,52 @@ struct ReferenceStorageTypeLayout<T, ObjC: C> {
var z: T
// -- ObjC-refcounted class
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBOXoWV", i32 9)
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBOXoWV", i32 8)
unowned(safe) var cs: C
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBomWV", i32 9)
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBomWV", i32 8)
unowned(unsafe) var cu: C
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBOSgXwWV", i32 9)
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBOSgXwWV", i32 8)
weak var cwo: C?
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBOSgXwWV", i32 9)
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBOSgXwWV", i32 8)
weak var cwi: C!
// -- ObjC-refcounted archetype
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBOXoWV", i32 9)
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBOXoWV", i32 8)
unowned(safe) var os: ObjC
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBomWV", i32 9)
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBomWV", i32 8)
unowned(unsafe) var ou: ObjC
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBOSgXwWV", i32 9)
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBOSgXwWV", i32 8)
weak var owo: ObjC?
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBOSgXwWV", i32 9)
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBOSgXwWV", i32 8)
weak var owi: ObjC!
// -- Pure ObjC protocols are unknown-refcounted
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBOXoWV", i32 9)
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBOXoWV", i32 8)
unowned(safe) var ps: P
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBomWV", i32 9)
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBomWV", i32 8)
unowned(unsafe) var pu: P
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBOSgXwWV", i32 9)
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBOSgXwWV", i32 8)
weak var pwo: P?
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBOSgXwWV", i32 9)
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBOSgXwWV", i32 8)
weak var pwi: P!
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBOXoWV", i32 9)
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBOXoWV", i32 8)
unowned(safe) var pqs: P & Q
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBomWV", i32 9)
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBomWV", i32 8)
unowned(unsafe) var pqu: P & Q
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBOSgXwWV", i32 9)
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBOSgXwWV", i32 8)
weak var pqwo: (P & Q)?
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBOSgXwWV", i32 9)
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBOSgXwWV", i32 8)
weak var pqwi: (P & Q)!
// -- Composition with ObjC protocol and native class is native-refcounted
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBoXoWV", i32 9)
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBoXoWV", i32 8)
unowned(safe) var pncs: (P & NativeClass)
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBomWV", i32 9)
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBomWV", i32 8)
unowned(unsafe) var pncu: (P & NativeClass)
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBoSgXwWV", i32 9)
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBoSgXwWV", i32 8)
weak var pncwo: (P & NativeClass)?
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBoSgXwWV", i32 9)
// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBoSgXwWV", i32 8)
weak var pncwi: (P & NativeClass)!
// -- Open-code layouts when there are witness tables.

View File

@@ -24,7 +24,6 @@ struct Gen<T> {
var x: C
var y: T
}
// CHECK: @"$S20weak_value_witnesses8JustWeakVWV" = internal constant [12 x i8*] {{.*}}@__swift_copy_outline_existential_box_pointer
// CHECK-NOT: define linkonce_odr hidden %swift.opaque* @"$S20weak_value_witnesses8JustWeakVwTK"(

View File

@@ -658,48 +658,6 @@ namespace swift {
ValueWitnessTable *vwtable);
} // namespace swift
TEST(MetadataTest, installCommonValueWitnesses_pod_indirect) {
ValueWitnessTable testTable;
FullMetadata<Metadata> testMetadata{{&testTable}, {MetadataKind::Opaque}};
// rdar://problem/21375421 - pod_indirect_initializeBufferWithTakeOfBuffer
// should move ownership of a fixed-size buffer.
testTable.size = sizeof(ValueBuffer) + 1;
testTable.flags = ValueWitnessFlags()
.withAlignment(alignof(ValueBuffer))
.withPOD(true)
.withBitwiseTakable(true)
.withInlineStorage(false);
testTable.stride = sizeof(ValueBuffer) + alignof(ValueBuffer);
installCommonValueWitnesses(*testTable.getTypeLayout(), &testTable);
// Replace allocateBuffer and destroyBuffer with logging versions.
struct {
ValueBuffer buffer;
uintptr_t canary;
} buf1{{}, 0x5A5A5A5AU}, buf2{{}, 0xA5A5A5A5U};
testMetadata.allocateBoxForExistentialIn(&buf1.buffer);
testTable.initializeBufferWithTakeOfBuffer(&buf2.buffer, &buf1.buffer,
&testMetadata);
// The existential's box reference should be copied.
EXPECT_EQ(buf1.buffer.PrivateData[0], buf2.buffer.PrivateData[0]);
// Ownership of the box should have been transferred.
auto *reference = reinterpret_cast<HeapObject *>(buf2.buffer.PrivateData[0]);
EXPECT_TRUE(swift_isUniquelyReferencedOrPinned_nonNull_native(reference));
EXPECT_EQ(buf1.canary, (uintptr_t)0x5A5A5A5AU);
EXPECT_EQ(buf2.canary, (uintptr_t)0xA5A5A5A5U);
// Release the buffer.
swift_release(reference);
}
// We cannot construct RelativeDirectPointer instances, so define
// a "shadow" struct for that purpose
struct GenericWitnessTableStorage {