From f4db36426c047ff23b693fd82690a1e2bc61c87b Mon Sep 17 00:00:00 2001 From: Joe Shajrawi Date: Sat, 28 Oct 2017 12:42:05 -0700 Subject: [PATCH] Code Size: Outline copy addr instruction --- docs/ABI/Mangling.rst | 4 + include/swift/Demangling/DemangleNodes.def | 4 + include/swift/Serialization/ModuleFormat.h | 2 +- lib/Demangling/Demangler.cpp | 17 +++ lib/Demangling/NodePrinter.cpp | 20 ++++ lib/Demangling/OldRemangler.cpp | 20 ++++ lib/Demangling/Remangler.cpp | 20 ++++ lib/IRGen/GenDecl.cpp | 89 ++++++++++++++- lib/IRGen/GenEnum.cpp | 80 ++++++++++++-- lib/IRGen/GenExistential.cpp | 104 ++++++++++++------ lib/IRGen/GenRecord.h | 3 +- lib/IRGen/GenType.cpp | 12 +- lib/IRGen/IRGenFunction.cpp | 9 +- lib/IRGen/IRGenFunction.h | 12 +- lib/IRGen/IRGenMangler.h | 25 +++++ lib/IRGen/IRGenModule.h | 26 +++++ lib/IRGen/IRGenSIL.cpp | 1 - .../enum_value_semantics_special_cases.sil | 87 +++++---------- test/IRGen/existentials.sil | 32 +----- test/IRGen/existentials_objc.sil | 45 ++------ test/IRGen/existentials_opaque_boxed.sil | 51 ++++----- test/IRGen/unowned_objc.sil | 32 +----- 22 files changed, 466 insertions(+), 229 deletions(-) diff --git a/docs/ABI/Mangling.rst b/docs/ABI/Mangling.rst index c1453daf4ea1d..d30e45e982390 100644 --- a/docs/ABI/Mangling.rst +++ b/docs/ABI/Mangling.rst @@ -83,6 +83,10 @@ Globals global ::= type 'We' // Outlined Consume Function Type global ::= type 'Wr' // Outlined Retain Function Type global ::= type 'Ws' // Outlined Release Function Type + global ::= type 'Wb' // Outlined InitializeWithTake Function Type + global ::= type 'Wc' // Outlined InitializeWithCopy Function Type + global ::= type 'Wd' // Outlined AssignWithTake Function Type + global ::= type 'Wf' // Outlined AssignWithCopy Function Type assoc_type_path ::= identifier '_' identifier* diff --git a/include/swift/Demangling/DemangleNodes.def b/include/swift/Demangling/DemangleNodes.def index bac3a231d6ced..18bf858051fe4 100644 --- a/include/swift/Demangling/DemangleNodes.def +++ b/include/swift/Demangling/DemangleNodes.def @@ -189,6 +189,10 @@ NODE(OutlinedCopy) NODE(OutlinedConsume) NODE(OutlinedRetain) NODE(OutlinedRelease) +NODE(OutlinedInitializeWithTake) +NODE(OutlinedInitializeWithCopy) +NODE(OutlinedAssignWithTake) +NODE(OutlinedAssignWithCopy) NODE(OutlinedVariable) NODE(AssocTypePath) #undef CONTEXT_NODE diff --git a/include/swift/Serialization/ModuleFormat.h b/include/swift/Serialization/ModuleFormat.h index f06a7a400cda6..b8db66cf68d12 100644 --- a/include/swift/Serialization/ModuleFormat.h +++ b/include/swift/Serialization/ModuleFormat.h @@ -54,7 +54,7 @@ const uint16_t VERSION_MAJOR = 0; /// in source control, you should also update the comment to briefly /// describe what change you made. The content of this comment isn't important; /// it just ensures a conflict if two people change the module format. -const uint16_t VERSION_MINOR = 372; // Last change: VTable serialized +const uint16_t VERSION_MINOR = 373; // Last change: Outlined CopyAddr using DeclID = PointerEmbeddedInt; using DeclIDField = BCFixed<31>; diff --git a/lib/Demangling/Demangler.cpp b/lib/Demangling/Demangler.cpp index 76e9235da7dbf..a68dbf912f1ad 100644 --- a/lib/Demangling/Demangler.cpp +++ b/lib/Demangling/Demangler.cpp @@ -1687,6 +1687,23 @@ NodePointer Demangler::demangleWitness() { return createWithChild(Node::Kind::OutlinedRelease, popNode(Node::Kind::Type)); } + case 'b': { + return createWithChild(Node::Kind::OutlinedInitializeWithTake, + popNode(Node::Kind::Type)); + } + case 'c': { + return createWithChild(Node::Kind::OutlinedInitializeWithCopy, + popNode(Node::Kind::Type)); + } + case 'd': { + return createWithChild(Node::Kind::OutlinedAssignWithTake, + popNode(Node::Kind::Type)); + } + case 'f': { + return createWithChild(Node::Kind::OutlinedAssignWithCopy, + popNode(Node::Kind::Type)); + } + default: return nullptr; } diff --git a/lib/Demangling/NodePrinter.cpp b/lib/Demangling/NodePrinter.cpp index 52227b6d5bd44..c16b35aaf0e79 100644 --- a/lib/Demangling/NodePrinter.cpp +++ b/lib/Demangling/NodePrinter.cpp @@ -416,6 +416,10 @@ class NodePrinter { case Node::Kind::OutlinedConsume: case Node::Kind::OutlinedRetain: case Node::Kind::OutlinedRelease: + case Node::Kind::OutlinedInitializeWithTake: + case Node::Kind::OutlinedInitializeWithCopy: + case Node::Kind::OutlinedAssignWithTake: + case Node::Kind::OutlinedAssignWithCopy: case Node::Kind::OutlinedVariable: case Node::Kind::AssocTypePath: return false; @@ -809,6 +813,22 @@ NodePointer NodePrinter::print(NodePointer Node, bool asPrefixContext) { Printer << "outlined release of "; print(Node->getChild(0)); return nullptr; + case Node::Kind::OutlinedInitializeWithTake: + Printer << "outlined init with take of "; + print(Node->getChild(0)); + return nullptr; + case Node::Kind::OutlinedInitializeWithCopy: + Printer << "outlined init with copy of "; + print(Node->getChild(0)); + return nullptr; + case Node::Kind::OutlinedAssignWithTake: + Printer << "outlined assign with take of "; + print(Node->getChild(0)); + return nullptr; + case Node::Kind::OutlinedAssignWithCopy: + Printer << "outlined assign with copy of "; + print(Node->getChild(0)); + return nullptr; case Node::Kind::OutlinedVariable: Printer << "outlined variable #" << Node->getIndex() << " of "; return nullptr; diff --git a/lib/Demangling/OldRemangler.cpp b/lib/Demangling/OldRemangler.cpp index f865ecff14bbd..3666b4364249f 100644 --- a/lib/Demangling/OldRemangler.cpp +++ b/lib/Demangling/OldRemangler.cpp @@ -1700,6 +1700,26 @@ void Remangler::mangleOutlinedRelease(Node *node) { mangleSingleChildNode(node); } +void Remangler::mangleOutlinedInitializeWithTake(Node *node) { + Out << "Wb"; + mangleSingleChildNode(node); +} + +void Remangler::mangleOutlinedInitializeWithCopy(Node *node) { + Out << "Wc"; + mangleSingleChildNode(node); +} + +void Remangler::mangleOutlinedAssignWithTake(Node *node) { + Out << "Wd"; + mangleSingleChildNode(node); +} + +void Remangler::mangleOutlinedAssignWithCopy(Node *node) { + Out << "Wf"; + mangleSingleChildNode(node); +} + void Remangler::mangleOutlinedVariable(Node *node) { Out << "Tv" << node->getIndex(); mangleSingleChildNode(node); diff --git a/lib/Demangling/Remangler.cpp b/lib/Demangling/Remangler.cpp index 54ac466458135..060cc2480c721 100644 --- a/lib/Demangling/Remangler.cpp +++ b/lib/Demangling/Remangler.cpp @@ -1747,6 +1747,26 @@ void Remangler::mangleOutlinedRelease(Node *node) { Buffer << "Ws"; } +void Remangler::mangleOutlinedInitializeWithTake(Node *node) { + mangleSingleChildNode(node); + Buffer << "Wb"; +} + +void Remangler::mangleOutlinedInitializeWithCopy(Node *node) { + mangleSingleChildNode(node); + Buffer << "Wc"; +} + +void Remangler::mangleOutlinedAssignWithTake(Node *node) { + mangleSingleChildNode(node); + Buffer << "Wd"; +} + +void Remangler::mangleOutlinedAssignWithCopy(Node *node) { + mangleSingleChildNode(node); + Buffer << "Wf"; +} + void Remangler::mangleOutlinedVariable(Node *node) { Buffer << "Tv"; mangleIndex(node->getIndex()); diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp index 9351cb5d7be83..e36f5ce8d739f 100644 --- a/lib/IRGen/GenDecl.cpp +++ b/lib/IRGen/GenDecl.cpp @@ -19,6 +19,7 @@ #include "swift/AST/Decl.h" #include "swift/AST/DiagnosticEngine.h" #include "swift/AST/DiagnosticsIRGen.h" +#include "swift/AST/GenericEnvironment.h" #include "swift/AST/GenericSignature.h" #include "swift/AST/IRGenOptions.h" #include "swift/AST/Module.h" @@ -39,10 +40,10 @@ #include "clang/AST/GlobalDecl.h" #include "llvm/ADT/SmallString.h" #include "llvm/IR/GlobalAlias.h" +#include "llvm/IR/InlineAsm.h" #include "llvm/IR/Module.h" #include "llvm/IR/TypeBuilder.h" #include "llvm/IR/Value.h" -#include "llvm/IR/InlineAsm.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ConvertUTF.h" #include "llvm/Support/Path.h" @@ -3517,6 +3518,7 @@ llvm::Constant *IRGenModule::getOrCreateRetainFunction(const TypeInfo &objectTI, return getOrCreateHelperFunction( funcName, llvmType, argTys, [&](IRGenFunction &IGF) { + IGF.setInOutlinedFunction(); auto it = IGF.CurFn->arg_begin(); Address addr(&*it++, loadableTI->getFixedAlignment()); Explosion loaded; @@ -3540,6 +3542,7 @@ IRGenModule::getOrCreateReleaseFunction(const TypeInfo &objectTI, Type t, return getOrCreateHelperFunction( funcName, llvmType, argTys, [&](IRGenFunction &IGF) { + IGF.setInOutlinedFunction(); auto it = IGF.CurFn->arg_begin(); Address addr(&*it++, loadableTI->getFixedAlignment()); Explosion loaded; @@ -3549,3 +3552,87 @@ IRGenModule::getOrCreateReleaseFunction(const TypeInfo &objectTI, Type t, }, true /*setIsNoInline*/); } + +void IRGenModule::generateCallToOutlinedCopyAddr( + IRGenFunction &IGF, const TypeInfo &objectTI, Address dest, Address src, + SILType T, const OutlinedCopyAddrFunction MethodToCall) { + llvm::Type *llvmType = dest->getType(); + auto *outlinedF = (this->*MethodToCall)(objectTI, llvmType, T); + llvm::Value *args[] = {src.getAddress(), dest.getAddress()}; + llvm::CallInst *call = IGF.Builder.CreateCall(outlinedF, args); + call->setCallingConv(DefaultCC); +} + +llvm::Constant *IRGenModule::getOrCreateOutlinedCopyAddrHelperFunction( + const TypeInfo &objectTI, llvm::Type *llvmType, SILType addrTy, + std::string funcName, + llvm::function_ref + Generate) { + llvm::Type *argTys[] = {llvmType, llvmType}; + return getOrCreateHelperFunction( + funcName, llvmType, argTys, + [&](IRGenFunction &IGF) { + IGF.setInOutlinedFunction(); + auto it = IGF.CurFn->arg_begin(); + Address src(&*it++, objectTI.getBestKnownAlignment()); + Address dest(&*it++, objectTI.getBestKnownAlignment()); + Generate(objectTI, IGF, dest, src, addrTy); + IGF.Builder.CreateRet(dest.getAddress()); + }, + true /*setIsNoInline*/); +} + +llvm::Constant *IRGenModule::getOrCreateOutlinedInitializeWithTakeFunction( + const TypeInfo &objectTI, llvm::Type *llvmType, SILType addrTy) { + IRGenMangler mangler; + CanType canType = addrTy.getObjectType().getSwiftRValueType(); + std::string funcName = + mangler.mangleOutlinedInitializeWithTakeFunction(canType); + auto GenFunc = [this](const TypeInfo &objectTI, IRGenFunction &IGF, + Address dest, Address src, SILType T) { + objectTI.initializeWithTake(IGF, dest, src, T); + }; + return getOrCreateOutlinedCopyAddrHelperFunction(objectTI, llvmType, addrTy, + funcName, GenFunc); +} + +llvm::Constant *IRGenModule::getOrCreateOutlinedInitializeWithCopyFunction( + const TypeInfo &objectTI, llvm::Type *llvmType, SILType addrTy) { + IRGenMangler mangler; + CanType canType = addrTy.getObjectType().getSwiftRValueType(); + std::string funcName = + mangler.mangleOutlinedInitializeWithCopyFunction(canType); + auto GenFunc = [this](const TypeInfo &objectTI, IRGenFunction &IGF, + Address dest, Address src, SILType T) { + objectTI.initializeWithCopy(IGF, dest, src, T); + }; + return getOrCreateOutlinedCopyAddrHelperFunction(objectTI, llvmType, addrTy, + funcName, GenFunc); +} + +llvm::Constant *IRGenModule::getOrCreateOutlinedAssignWithTakeFunction( + const TypeInfo &objectTI, llvm::Type *llvmType, SILType addrTy) { + IRGenMangler mangler; + CanType canType = addrTy.getObjectType().getSwiftRValueType(); + std::string funcName = mangler.mangleOutlinedAssignWithTakeFunction(canType); + auto GenFunc = [this](const TypeInfo &objectTI, IRGenFunction &IGF, + Address dest, Address src, SILType T) { + objectTI.assignWithTake(IGF, dest, src, T); + }; + return getOrCreateOutlinedCopyAddrHelperFunction(objectTI, llvmType, addrTy, + funcName, GenFunc); +} + +llvm::Constant *IRGenModule::getOrCreateOutlinedAssignWithCopyFunction( + const TypeInfo &objectTI, llvm::Type *llvmType, SILType addrTy) { + IRGenMangler mangler; + CanType canType = addrTy.getObjectType().getSwiftRValueType(); + std::string funcName = mangler.mangleOutlinedAssignWithCopyFunction(canType); + auto GenFunc = [this](const TypeInfo &objectTI, IRGenFunction &IGF, + Address dest, Address src, SILType T) { + objectTI.assignWithCopy(IGF, dest, src, T); + }; + return getOrCreateOutlinedCopyAddrHelperFunction(objectTI, llvmType, addrTy, + funcName, GenFunc); +} diff --git a/lib/IRGen/GenEnum.cpp b/lib/IRGen/GenEnum.cpp index f3f3c1ab17479..b9e845df7ef9e 100644 --- a/lib/IRGen/GenEnum.cpp +++ b/lib/IRGen/GenEnum.cpp @@ -2598,25 +2598,57 @@ namespace { void assignWithCopy(IRGenFunction &IGF, Address dest, Address src, SILType T) const override { - emitIndirectAssign(IGF, dest, src, T, IsNotTake); + if (IGF.isInOutlinedFunction() || (TIK < Loadable) || + (T.hasArchetype())) { + emitIndirectAssign(IGF, dest, src, T, IsNotTake); + } else { + // Create an outlined function to avoid explosion + IGF.IGM.generateCallToOutlinedCopyAddr( + IGF, *TI, dest, src, T, + &IRGenModule::getOrCreateOutlinedAssignWithCopyFunction); + } } void assignWithTake(IRGenFunction &IGF, Address dest, Address src, SILType T) const override { - emitIndirectAssign(IGF, dest, src, T, IsTake); + if (IGF.isInOutlinedFunction() || (TIK < Loadable) || + (T.hasArchetype())) { + emitIndirectAssign(IGF, dest, src, T, IsTake); + } else { + // Create an outlined function to avoid explosion + IGF.IGM.generateCallToOutlinedCopyAddr( + IGF, *TI, dest, src, T, + &IRGenModule::getOrCreateOutlinedAssignWithTakeFunction); + } } void initializeWithCopy(IRGenFunction &IGF, Address dest, Address src, SILType T) const override { - emitIndirectInitialize(IGF, dest, src, T, IsNotTake); + if (IGF.isInOutlinedFunction() || (TIK < Loadable) || + (T.hasArchetype())) { + emitIndirectInitialize(IGF, dest, src, T, IsNotTake); + } else { + // Create an outlined function to avoid explosion + IGF.IGM.generateCallToOutlinedCopyAddr( + IGF, *TI, dest, src, T, + &IRGenModule::getOrCreateOutlinedInitializeWithCopyFunction); + } } void initializeWithTake(IRGenFunction &IGF, Address dest, Address src, SILType T) const override { - emitIndirectInitialize(IGF, dest, src, T, IsTake); + if (IGF.isInOutlinedFunction() || (TIK < Loadable) || + (T.hasArchetype())) { + emitIndirectInitialize(IGF, dest, src, T, IsTake); + } else { + // Create an outlined function to avoid explosion + IGF.IGM.generateCallToOutlinedCopyAddr( + IGF, *TI, dest, src, T, + &IRGenModule::getOrCreateOutlinedInitializeWithTakeFunction); + } } void storeTag(IRGenFunction &IGF, @@ -4211,25 +4243,57 @@ namespace { void assignWithCopy(IRGenFunction &IGF, Address dest, Address src, SILType T) const override { - emitIndirectAssign(IGF, dest, src, T, IsNotTake); + if (IGF.isInOutlinedFunction() || (TIK < Loadable) || + (T.hasArchetype())) { + emitIndirectAssign(IGF, dest, src, T, IsNotTake); + } else { + // Create an outlined function to avoid explosion + IGF.IGM.generateCallToOutlinedCopyAddr( + IGF, *TI, dest, src, T, + &IRGenModule::getOrCreateOutlinedAssignWithCopyFunction); + } } void assignWithTake(IRGenFunction &IGF, Address dest, Address src, SILType T) const override { - emitIndirectAssign(IGF, dest, src, T, IsTake); + if (IGF.isInOutlinedFunction() || (TIK < Loadable) || + (T.hasArchetype())) { + emitIndirectAssign(IGF, dest, src, T, IsTake); + } else { + // Create an outlined function to avoid explosion + IGF.IGM.generateCallToOutlinedCopyAddr( + IGF, *TI, dest, src, T, + &IRGenModule::getOrCreateOutlinedAssignWithTakeFunction); + } } void initializeWithCopy(IRGenFunction &IGF, Address dest, Address src, SILType T) const override { - emitIndirectInitialize(IGF, dest, src, T, IsNotTake); + if (IGF.isInOutlinedFunction() || (TIK < Loadable) || + (T.hasArchetype())) { + emitIndirectInitialize(IGF, dest, src, T, IsNotTake); + } else { + // Create an outlined function to avoid explosion + IGF.IGM.generateCallToOutlinedCopyAddr( + IGF, *TI, dest, src, T, + &IRGenModule::getOrCreateOutlinedInitializeWithCopyFunction); + } } void initializeWithTake(IRGenFunction &IGF, Address dest, Address src, SILType T) const override { - emitIndirectInitialize(IGF, dest, src, T, IsTake); + if (IGF.isInOutlinedFunction() || (TIK < Loadable) || + (T.hasArchetype())) { + emitIndirectInitialize(IGF, dest, src, T, IsTake); + } else { + // Create an outlined function to avoid explosion + IGF.IGM.generateCallToOutlinedCopyAddr( + IGF, *TI, dest, src, T, + &IRGenModule::getOrCreateOutlinedInitializeWithTakeFunction); + } } void destroy(IRGenFunction &IGF, Address addr, SILType T) const override { diff --git a/lib/IRGen/GenExistential.cpp b/lib/IRGen/GenExistential.cpp index fcf5fc8c41949..9e7b6ed71cae5 100644 --- a/lib/IRGen/GenExistential.cpp +++ b/lib/IRGen/GenExistential.cpp @@ -320,33 +320,45 @@ class OpaqueExistentialTypeInfo final : void initializeWithCopy(IRGenFunction &IGF, Address dest, Address src, SILType T) const override { - llvm::Value *metadata = copyType(IGF, dest, src); + if (IGF.isInOutlinedFunction()) { + llvm::Value *metadata = copyType(IGF, dest, src); - auto layout = getLayout(); + auto layout = getLayout(); - // Project down to the buffers and ask the witnesses to do a - // copy-initialize. - Address srcBuffer = layout.projectExistentialBuffer(IGF, src); - Address destBuffer = layout.projectExistentialBuffer(IGF, dest); - emitInitializeBufferWithCopyOfBufferCall(IGF, metadata, - destBuffer, - srcBuffer); + // Project down to the buffers and ask the witnesses to do a + // copy-initialize. + Address srcBuffer = layout.projectExistentialBuffer(IGF, src); + Address destBuffer = layout.projectExistentialBuffer(IGF, dest); + emitInitializeBufferWithCopyOfBufferCall(IGF, metadata, destBuffer, + srcBuffer); + } else { + // Create an outlined function to avoid explosion + IGF.IGM.generateCallToOutlinedCopyAddr( + IGF, *this, dest, src, T, + &IRGenModule::getOrCreateOutlinedInitializeWithCopyFunction); + } } void initializeWithTake(IRGenFunction &IGF, Address dest, Address src, SILType T) const override { - llvm::Value *metadata = copyType(IGF, dest, src); + if (IGF.isInOutlinedFunction()) { + llvm::Value *metadata = copyType(IGF, dest, src); - auto layout = getLayout(); + 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); + // 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); + } else { + // Create an outlined function to avoid explosion + IGF.IGM.generateCallToOutlinedCopyAddr( + IGF, *this, dest, src, T, + &IRGenModule::getOrCreateOutlinedInitializeWithTakeFunction); + } } void destroy(IRGenFunction &IGF, Address addr, SILType T) const override { @@ -398,37 +410,61 @@ class AddressOnlyClassExistentialTypeInfoBase : void assignWithCopy(IRGenFunction &IGF, Address dest, Address src, SILType T) const override { - Address destValue = projectValue(IGF, dest); - Address srcValue = projectValue(IGF, src); - asDerived().emitValueAssignWithCopy(IGF, destValue, srcValue); - emitCopyOfTables(IGF, dest, src); + if (IGF.isInOutlinedFunction()) { + Address destValue = projectValue(IGF, dest); + Address srcValue = projectValue(IGF, src); + asDerived().emitValueAssignWithCopy(IGF, destValue, srcValue); + emitCopyOfTables(IGF, dest, src); + } else { + IGF.IGM.generateCallToOutlinedCopyAddr( + IGF, *this, dest, src, T, + &IRGenModule::getOrCreateOutlinedAssignWithCopyFunction); + } } void initializeWithCopy(IRGenFunction &IGF, Address dest, Address src, SILType T) const override { - Address destValue = projectValue(IGF, dest); - Address srcValue = projectValue(IGF, src); - asDerived().emitValueInitializeWithCopy(IGF, destValue, srcValue); - emitCopyOfTables(IGF, dest, src); + if (IGF.isInOutlinedFunction()) { + Address destValue = projectValue(IGF, dest); + Address srcValue = projectValue(IGF, src); + asDerived().emitValueInitializeWithCopy(IGF, destValue, srcValue); + emitCopyOfTables(IGF, dest, src); + } else { + IGF.IGM.generateCallToOutlinedCopyAddr( + IGF, *this, dest, src, T, + &IRGenModule::getOrCreateOutlinedInitializeWithCopyFunction); + } } void assignWithTake(IRGenFunction &IGF, Address dest, Address src, SILType T) const override { - Address destValue = projectValue(IGF, dest); - Address srcValue = projectValue(IGF, src); - asDerived().emitValueAssignWithTake(IGF, destValue, srcValue); - emitCopyOfTables(IGF, dest, src); + if (IGF.isInOutlinedFunction()) { + Address destValue = projectValue(IGF, dest); + Address srcValue = projectValue(IGF, src); + asDerived().emitValueAssignWithTake(IGF, destValue, srcValue); + emitCopyOfTables(IGF, dest, src); + } else { + IGF.IGM.generateCallToOutlinedCopyAddr( + IGF, *this, dest, src, T, + &IRGenModule::getOrCreateOutlinedAssignWithTakeFunction); + } } void initializeWithTake(IRGenFunction &IGF, Address dest, Address src, SILType T) const override { - Address destValue = projectValue(IGF, dest); - Address srcValue = projectValue(IGF, src); - asDerived().emitValueInitializeWithTake(IGF, destValue, srcValue); - emitCopyOfTables(IGF, dest, src); + if (IGF.isInOutlinedFunction()) { + Address destValue = projectValue(IGF, dest); + Address srcValue = projectValue(IGF, src); + asDerived().emitValueInitializeWithTake(IGF, destValue, srcValue); + emitCopyOfTables(IGF, dest, src); + } else { + IGF.IGM.generateCallToOutlinedCopyAddr( + IGF, *this, dest, src, T, + &IRGenModule::getOrCreateOutlinedInitializeWithTakeFunction); + } } void destroy(IRGenFunction &IGF, Address existential, diff --git a/lib/IRGen/GenRecord.h b/lib/IRGen/GenRecord.h index 4e01538b5d5e8..6ef1404527a03 100644 --- a/lib/IRGen/GenRecord.h +++ b/lib/IRGen/GenRecord.h @@ -173,7 +173,8 @@ class RecordTypeInfoImpl : public Base, auto offsets = asImpl().getNonFixedOffsets(IGF, T); for (auto &field : getFields()) { - if (field.isEmpty()) continue; + if (field.isEmpty()) + continue; Address destField = field.projectAddress(IGF, dest, offsets); Address srcField = field.projectAddress(IGF, src, offsets); diff --git a/lib/IRGen/GenType.cpp b/lib/IRGen/GenType.cpp index a45fd0a075372..9ff55de75ad9d 100644 --- a/lib/IRGen/GenType.cpp +++ b/lib/IRGen/GenType.cpp @@ -158,9 +158,15 @@ void LoadableTypeInfo::initializeWithCopy(IRGenFunction &IGF, } // Otherwise explode and re-implode. - Explosion copy; - loadAsCopy(IGF, srcAddr, copy); - initialize(IGF, copy, destAddr); + if (IGF.isInOutlinedFunction()) { + Explosion copy; + loadAsCopy(IGF, srcAddr, copy); + initialize(IGF, copy, destAddr); + } else { + IGF.IGM.generateCallToOutlinedCopyAddr( + IGF, *this, destAddr, srcAddr, T, + &IRGenModule::getOrCreateOutlinedInitializeWithCopyFunction); + } } LoadedRef LoadableTypeInfo::loadRefcountedPtr(IRGenFunction &IGF, diff --git a/lib/IRGen/IRGenFunction.cpp b/lib/IRGen/IRGenFunction.cpp index ff0ac8624d4fc..3dd914d22d019 100644 --- a/lib/IRGen/IRGenFunction.cpp +++ b/lib/IRGen/IRGenFunction.cpp @@ -36,7 +36,7 @@ IRGenFunction::IRGenFunction(IRGenModule &IGM, llvm::Function *Fn, Optional DbgLoc) : IGM(IGM), Builder(IGM.getLLVMContext(), IGM.DebugInfo && !IGM.Context.LangOpts.DebuggerSupport), - CurFn(Fn), DbgScope(DbgScope) { + CurFn(Fn), DbgScope(DbgScope), inOutlinedFunction(false) { // Make sure the instructions in this function are attached its debug scope. if (IGM.DebugInfo) { @@ -422,3 +422,10 @@ Address IRGenFunction::emitAddressAtOffset(llvm::Value *base, Offset offset, auto slotPtr = emitByteOffsetGEP(base, offsetValue, objectTy); return Address(slotPtr, objectAlignment); } + +bool IRGenFunction::isInOutlinedFunction() { return inOutlinedFunction; } + +void IRGenFunction::setInOutlinedFunction() { + assert(!isInOutlinedFunction() && "Expected inOutlinedFunction to be false"); + inOutlinedFunction = true; +} diff --git a/lib/IRGen/IRGenFunction.h b/lib/IRGen/IRGenFunction.h index f231f8e86590e..507cddb89909d 100644 --- a/lib/IRGen/IRGenFunction.h +++ b/lib/IRGen/IRGenFunction.h @@ -554,7 +554,13 @@ class IRGenFunction { llvm::Value *getLocalSelfMetadata(); void setLocalSelfMetadata(llvm::Value *value, LocalSelfKind kind); - + +public: + //--- Outlined Function Support ------------------------------------------- +public: + bool isInOutlinedFunction(); + void setInOutlinedFunction(); + private: LocalTypeDataCache &getOrCreateLocalTypeData(); void destroyLocalTypeData(); @@ -571,6 +577,10 @@ class IRGenFunction { llvm::Value *LocalSelf = nullptr; LocalSelfKind SelfKind; + + /// Flag indiacting wherever we are in the middle of creating + /// an outlined address type function + bool inOutlinedFunction; }; using ConditionalDominanceScope = IRGenFunction::ConditionalDominanceScope; diff --git a/lib/IRGen/IRGenMangler.h b/lib/IRGen/IRGenMangler.h index b4e2b97ef6014..6eff174580548 100644 --- a/lib/IRGen/IRGenMangler.h +++ b/lib/IRGen/IRGenMangler.h @@ -173,6 +173,31 @@ class IRGenMangler : public Mangle::ASTMangler { return finalize(); } + std::string mangleOutlinedInitializeWithTakeFunction(const Type t) { + beginMangling(); + appendType(t); + appendOperator("Wb"); + return finalize(); + } + std::string mangleOutlinedInitializeWithCopyFunction(const Type t) { + beginMangling(); + appendType(t); + appendOperator("Wc"); + return finalize(); + } + std::string mangleOutlinedAssignWithTakeFunction(const Type t) { + beginMangling(); + appendType(t); + appendOperator("Wd"); + return finalize(); + } + std::string mangleOutlinedAssignWithCopyFunction(const Type t) { + beginMangling(); + appendType(t); + appendOperator("Wf"); + return finalize(); + } + std::string manglePartialApplyForwarder(StringRef FuncName); std::string mangleTypeForMetadata(Type type) { diff --git a/lib/IRGen/IRGenModule.h b/lib/IRGen/IRGenModule.h index b1fa7a522837e..b242a3120a7c8 100644 --- a/lib/IRGen/IRGenModule.h +++ b/lib/IRGen/IRGenModule.h @@ -712,9 +712,35 @@ class IRGenModule { llvm::Constant *getOrCreateReleaseFunction(const TypeInfo &objectTI, Type t, llvm::Type *llvmType); + typedef llvm::Constant *(IRGenModule::*OutlinedCopyAddrFunction)( + const TypeInfo &objectTI, llvm::Type *llvmType, SILType addrTy); + + void + generateCallToOutlinedCopyAddr(IRGenFunction &IGF, const TypeInfo &objectTI, + Address dest, Address src, SILType T, + const OutlinedCopyAddrFunction MethodToCall); + + llvm::Constant *getOrCreateOutlinedInitializeWithTakeFunction( + const TypeInfo &objectTI, llvm::Type *llvmType, SILType addrTy); + + llvm::Constant *getOrCreateOutlinedInitializeWithCopyFunction( + const TypeInfo &objectTI, llvm::Type *llvmType, SILType addrTy); + + llvm::Constant *getOrCreateOutlinedAssignWithTakeFunction( + const TypeInfo &objectTI, llvm::Type *llvmType, SILType addrTy); + + llvm::Constant *getOrCreateOutlinedAssignWithCopyFunction( + const TypeInfo &objectTI, llvm::Type *llvmType, SILType addrTy); + private: llvm::Constant *getAddrOfClangGlobalDecl(clang::GlobalDecl global, ForDefinition_t forDefinition); + llvm::Constant *getOrCreateOutlinedCopyAddrHelperFunction( + const TypeInfo &objectTI, llvm::Type *llvmType, SILType addrTy, + std::string funcName, + llvm::function_ref + Generate); llvm::DenseMap GlobalVars; llvm::DenseMap GlobalGOTEquivalents; diff --git a/lib/IRGen/IRGenSIL.cpp b/lib/IRGen/IRGenSIL.cpp index a8b5300249d46..fa3bd1f2a4479 100644 --- a/lib/IRGen/IRGenSIL.cpp +++ b/lib/IRGen/IRGenSIL.cpp @@ -5015,7 +5015,6 @@ void IRGenSILFunction::visitCopyAddrInst(swift::CopyAddrInst *i) { auto &loweredDest = getLoweredValue(i->getDest()); assert(!loweredDest.isUnallocatedAddressInBuffer()); Address dest = loweredDest.getAnyAddress(); - if (i->isInitializationOfDest()) { if (i->isTakeOfSrc()) { addrTI.initializeWithTake(*this, dest, src, addrTy); diff --git a/test/IRGen/enum_value_semantics_special_cases.sil b/test/IRGen/enum_value_semantics_special_cases.sil index 198f76157521a..f07f6561856c7 100644 --- a/test/IRGen/enum_value_semantics_special_cases.sil +++ b/test/IRGen/enum_value_semantics_special_cases.sil @@ -24,42 +24,27 @@ enum NullableRefcounted { // CHECK: entry: // CHECK: %0 = bitcast %swift.opaque* %dest to %T34enum_value_semantics_special_cases18NullableRefcountedO* // CHECK: %1 = bitcast %swift.opaque* %src to %T34enum_value_semantics_special_cases18NullableRefcountedO* -// CHECK: %2 = bitcast %T34enum_value_semantics_special_cases18NullableRefcountedO* %0 to %swift.refcounted** -// CHECK: %3 = bitcast %T34enum_value_semantics_special_cases18NullableRefcountedO* %1 to %swift.refcounted** -// CHECK: %4 = load %swift.refcounted*, %swift.refcounted** %3, align 8 -// CHECK: call %swift.refcounted* @swift_rt_swift_retain(%swift.refcounted* returned %4) {{#[0-9]+}} -// CHECK: store %swift.refcounted* %4, %swift.refcounted** %2, align 8 -// CHECK: %6 = bitcast %T34enum_value_semantics_special_cases18NullableRefcountedO* %0 to %swift.opaque* -// CHECK: ret %swift.opaque* %6 +// CHECK: %2 = call %T34enum_value_semantics_special_cases18NullableRefcountedO* @_T034enum_value_semantics_special_cases18NullableRefcountedOWc(%T34enum_value_semantics_special_cases18NullableRefcountedO* %1, %T34enum_value_semantics_special_cases18NullableRefcountedO* %0) +// CHECK: %3 = bitcast %T34enum_value_semantics_special_cases18NullableRefcountedO* %0 to %swift.opaque* +// CHECK: ret %swift.opaque* %3 // CHECK: } // CHECK-LABEL: define linkonce_odr hidden %swift.opaque* @_T034enum_value_semantics_special_cases18NullableRefcountedOwca(%swift.opaque* %dest, %swift.opaque* %src, %swift.type* %NullableRefcounted) {{.*}} { // CHECK: entry: // CHECK: %0 = bitcast %swift.opaque* %dest to %T34enum_value_semantics_special_cases18NullableRefcountedO* // CHECK: %1 = bitcast %swift.opaque* %src to %T34enum_value_semantics_special_cases18NullableRefcountedO* -// CHECK: %2 = bitcast %T34enum_value_semantics_special_cases18NullableRefcountedO* %0 to %swift.refcounted** -// CHECK: %3 = bitcast %T34enum_value_semantics_special_cases18NullableRefcountedO* %1 to %swift.refcounted** -// CHECK: %4 = load %swift.refcounted*, %swift.refcounted** %2, align 8 -// CHECK: %5 = load %swift.refcounted*, %swift.refcounted** %3, align 8 -// CHECK: call %swift.refcounted* @swift_rt_swift_retain(%swift.refcounted* returned %5) {{#[0-9]+}} -// CHECK: store %swift.refcounted* %5, %swift.refcounted** %2, align 8 -// CHECK: call void @swift_rt_swift_release(%swift.refcounted* %4) {{#[0-9]+}} -// CHECK: %7 = bitcast %T34enum_value_semantics_special_cases18NullableRefcountedO* %0 to %swift.opaque* -// CHECK: ret %swift.opaque* %7 +// CHECK: %2 = call %T34enum_value_semantics_special_cases18NullableRefcountedO* @_T034enum_value_semantics_special_cases18NullableRefcountedOWf(%T34enum_value_semantics_special_cases18NullableRefcountedO* %1, %T34enum_value_semantics_special_cases18NullableRefcountedO* %0) +// CHECK: %3 = bitcast %T34enum_value_semantics_special_cases18NullableRefcountedO* %0 to %swift.opaque* +// CHECK: ret %swift.opaque* %3 // CHECK: } // CHECK-LABEL: define linkonce_odr hidden %swift.opaque* @_T034enum_value_semantics_special_cases18NullableRefcountedOwta(%swift.opaque* noalias %dest, %swift.opaque* noalias %src, %swift.type* %NullableRefcounted) {{.*}} { // CHECK: entry: // CHECK: %0 = bitcast %swift.opaque* %dest to %T34enum_value_semantics_special_cases18NullableRefcountedO* // CHECK: %1 = bitcast %swift.opaque* %src to %T34enum_value_semantics_special_cases18NullableRefcountedO* -// CHECK: %2 = bitcast %T34enum_value_semantics_special_cases18NullableRefcountedO* %0 to %swift.refcounted** -// CHECK: %3 = bitcast %T34enum_value_semantics_special_cases18NullableRefcountedO* %1 to %swift.refcounted** -// CHECK: %4 = load %swift.refcounted*, %swift.refcounted** %2, align 8 -// CHECK: %5 = load %swift.refcounted*, %swift.refcounted** %3, align 8 -// CHECK: store %swift.refcounted* %5, %swift.refcounted** %2, align 8 -// CHECK: call void @swift_rt_swift_release(%swift.refcounted* %4) {{#[0-9]+}} -// CHECK: %6 = bitcast %T34enum_value_semantics_special_cases18NullableRefcountedO* %0 to %swift.opaque* -// CHECK: ret %swift.opaque* %6 +// CHECK: %2 = call %T34enum_value_semantics_special_cases18NullableRefcountedO* @_T034enum_value_semantics_special_cases18NullableRefcountedOWd(%T34enum_value_semantics_special_cases18NullableRefcountedO* %1, %T34enum_value_semantics_special_cases18NullableRefcountedO* %0) +// CHECK: %3 = bitcast %T34enum_value_semantics_special_cases18NullableRefcountedO* %0 to %swift.opaque* +// CHECK: ret %swift.opaque* %3 // CHECK: } // Enums consisting of a retainable block pointer and a single empty case use @@ -82,42 +67,27 @@ enum NullableBlockRefcounted { // CHECK: entry: // CHECK: %0 = bitcast %swift.opaque* %dest to %T34enum_value_semantics_special_cases23NullableBlockRefcountedO* // CHECK: %1 = bitcast %swift.opaque* %src to %T34enum_value_semantics_special_cases23NullableBlockRefcountedO* -// CHECK: %2 = bitcast %T34enum_value_semantics_special_cases23NullableBlockRefcountedO* %0 to %objc_block** -// CHECK: %3 = bitcast %T34enum_value_semantics_special_cases23NullableBlockRefcountedO* %1 to %objc_block** -// CHECK: %4 = load %objc_block*, %objc_block** %3, align 8 -// CHECK: %5 = call %objc_block* @_Block_copy(%objc_block* %4) -// CHECK: store %objc_block* %4, %objc_block** %2, align 8 -// CHECK: %6 = bitcast %T34enum_value_semantics_special_cases23NullableBlockRefcountedO* %0 to %swift.opaque* -// CHECK: ret %swift.opaque* %6 +// CHECK: %2 = call %T34enum_value_semantics_special_cases23NullableBlockRefcountedO* @_T034enum_value_semantics_special_cases23NullableBlockRefcountedOWc(%T34enum_value_semantics_special_cases23NullableBlockRefcountedO* %1, %T34enum_value_semantics_special_cases23NullableBlockRefcountedO* %0) +// CHECK: %3 = bitcast %T34enum_value_semantics_special_cases23NullableBlockRefcountedO* %0 to %swift.opaque* +// CHECK: ret %swift.opaque* %3 // CHECK: } // CHECK-LABEL: define linkonce_odr hidden %swift.opaque* @_T034enum_value_semantics_special_cases23NullableBlockRefcountedOwca(%swift.opaque* %dest, %swift.opaque* %src, %swift.type* %NullableBlockRefcounted) {{.*}} { // CHECK: entry: // CHECK: %0 = bitcast %swift.opaque* %dest to %T34enum_value_semantics_special_cases23NullableBlockRefcountedO* // CHECK: %1 = bitcast %swift.opaque* %src to %T34enum_value_semantics_special_cases23NullableBlockRefcountedO* -// CHECK: %2 = bitcast %T34enum_value_semantics_special_cases23NullableBlockRefcountedO* %0 to %objc_block** -// CHECK: %3 = bitcast %T34enum_value_semantics_special_cases23NullableBlockRefcountedO* %1 to %objc_block** -// CHECK: %4 = load %objc_block*, %objc_block** %2, align 8 -// CHECK: %5 = load %objc_block*, %objc_block** %3, align 8 -// CHECK: %6 = call %objc_block* @_Block_copy(%objc_block* %5) -// CHECK: store %objc_block* %5, %objc_block** %2, align 8 -// CHECK: call void @_Block_release(%objc_block* %4) {{#[0-9]+}} -// CHECK: %7 = bitcast %T34enum_value_semantics_special_cases23NullableBlockRefcountedO* %0 to %swift.opaque* -// CHECK: ret %swift.opaque* %7 +// CHECK: %2 = call %T34enum_value_semantics_special_cases23NullableBlockRefcountedO* @_T034enum_value_semantics_special_cases23NullableBlockRefcountedOWf(%T34enum_value_semantics_special_cases23NullableBlockRefcountedO* %1, %T34enum_value_semantics_special_cases23NullableBlockRefcountedO* %0) +// CHECK: %3 = bitcast %T34enum_value_semantics_special_cases23NullableBlockRefcountedO* %0 to %swift.opaque* +// CHECK: ret %swift.opaque* %3 // CHECK: } // CHECK-LABEL: define linkonce_odr hidden %swift.opaque* @_T034enum_value_semantics_special_cases23NullableBlockRefcountedOwta(%swift.opaque* noalias %dest, %swift.opaque* noalias %src, %swift.type* %NullableBlockRefcounted) {{.*}} { // CHECK: entry: // CHECK: %0 = bitcast %swift.opaque* %dest to %T34enum_value_semantics_special_cases23NullableBlockRefcountedO* // CHECK: %1 = bitcast %swift.opaque* %src to %T34enum_value_semantics_special_cases23NullableBlockRefcountedO* -// CHECK: %2 = bitcast %T34enum_value_semantics_special_cases23NullableBlockRefcountedO* %0 to %objc_block** -// CHECK: %3 = bitcast %T34enum_value_semantics_special_cases23NullableBlockRefcountedO* %1 to %objc_block** -// CHECK: %4 = load %objc_block*, %objc_block** %2, align 8 -// CHECK: %5 = load %objc_block*, %objc_block** %3, align 8 -// CHECK: store %objc_block* %5, %objc_block** %2, align 8 -// CHECK: call void @_Block_release(%objc_block* %4) {{#[0-9]+}} -// CHECK: %6 = bitcast %T34enum_value_semantics_special_cases23NullableBlockRefcountedO* %0 to %swift.opaque* -// CHECK: ret %swift.opaque* %6 +// CHECK: %2 = call %T34enum_value_semantics_special_cases23NullableBlockRefcountedO* @_T034enum_value_semantics_special_cases23NullableBlockRefcountedOWd(%T34enum_value_semantics_special_cases23NullableBlockRefcountedO* %1, %T34enum_value_semantics_special_cases23NullableBlockRefcountedO* %0) +// CHECK: %3 = bitcast %T34enum_value_semantics_special_cases23NullableBlockRefcountedO* %0 to %swift.opaque* +// CHECK: ret %swift.opaque* %3 // CHECK: } // With multiple empty cases, the nullable pointer semantics aren't used. @@ -164,6 +134,16 @@ enum AllRefcounted { case None } +// CHECK-LABEL: define linkonce_odr hidden %T34enum_value_semantics_special_cases13AllRefcountedO* @_T034enum_value_semantics_special_cases13AllRefcountedOWc(%T34enum_value_semantics_special_cases13AllRefcountedO*, %T34enum_value_semantics_special_cases13AllRefcountedO*) +// -- 0x3fffffffffffffff +// CHECK: %4 = and i64 %3, 4611686018427387903 +// CHECK: %5 = inttoptr i64 %4 to %swift.refcounted* +// CHECK: call %swift.refcounted* @swift_rt_swift_retain(%swift.refcounted* returned %5) +// CHECK: %7 = bitcast %T34enum_value_semantics_special_cases13AllRefcountedO* %1 to i64* +// -- NB: The original loaded value is stored, not the masked one. +// CHECK: store i64 %3, i64* %7, align 8 +// CHECK: } + // CHECK-LABEL: define linkonce_odr hidden void @_T034enum_value_semantics_special_cases13AllRefcountedOwxx(%swift.opaque* noalias %object, %swift.type* %AllRefcounted) {{.*}} { // CHECK: entry: // CHECK: %0 = bitcast %swift.opaque* %object to %T34enum_value_semantics_special_cases13AllRefcountedO* @@ -176,17 +156,6 @@ enum AllRefcounted { // CHECK: ret void // CHECK: } -// CHECK-LABEL: define linkonce_odr hidden %swift.opaque* @_T034enum_value_semantics_special_cases13AllRefcountedOwcp(%swift.opaque* noalias %dest, %swift.opaque* noalias %src, %swift.type* %AllRefcounted) {{.*}} { -// CHECK: %3 = load i64, i64* %2, align 8 -// -- 0x3fffffffffffffff -// CHECK: %4 = and i64 %3, 4611686018427387903 -// CHECK: %5 = inttoptr i64 %4 to %swift.refcounted* -// CHECK: call %swift.refcounted* @swift_rt_swift_retain(%swift.refcounted* returned %5) -// CHECK: %6 = bitcast %T34enum_value_semantics_special_cases13AllRefcountedO* %0 to i64* -// -- NB: The original loaded value is stored, not the masked one. -// CHECK: store i64 %3, i64* %6, align 8 -// CHECK: } - enum AllRefcountedTwoSimple { case Ref(Builtin.NativeObject) case CRef(C) diff --git a/test/IRGen/existentials.sil b/test/IRGen/existentials.sil index a07d4a994bf93..e0fae89a49cf8 100644 --- a/test/IRGen/existentials.sil +++ b/test/IRGen/existentials.sil @@ -67,40 +67,16 @@ entry(%w : $*@sil_weak CP?, %a : $CP?): // CHECK: [[DEST_WITNESS:%.*]] = load i8**, i8*** [[SRC_WITNESS_ADDR]] %c = load_weak %w : $*@sil_weak CP? - // CHECK: [[DEST_REF_ADDR:%.*]] = getelementptr inbounds { %swift.weak, i8** }, { %swift.weak, i8** }* [[V]], i32 0, i32 0 - // CHECK: [[SRC_REF_ADDR:%.*]] = getelementptr inbounds { %swift.weak, i8** }, { %swift.weak, i8** }* %0, i32 0, i32 0 - // CHECK: call %swift.weak* @swift_weakTakeInit(%swift.weak* returned [[DEST_REF_ADDR]], %swift.weak* [[SRC_REF_ADDR]]) - // CHECK: [[SRC_WITNESS_ADDR:%.*]] = getelementptr inbounds { %swift.weak, i8** }, { %swift.weak, i8** }* %0, i32 0, i32 1 - // CHECK: [[WITNESS:%.*]] = load i8**, i8*** [[SRC_WITNESS_ADDR]], align 8 - // CHECK: [[DEST_WITNESS_ADDR:%.*]] = getelementptr inbounds { %swift.weak, i8** }, { %swift.weak, i8** }* [[V]], i32 0, i32 1 - // CHECK: store i8** [[WITNESS]], i8*** [[DEST_WITNESS_ADDR]], align 8 + // CHECK: call { %swift.weak, i8** }* @_T012existentials2CP_pSgXwWb({ %swift.weak, i8** }* %0, { %swift.weak, i8** }* [[V]]) copy_addr [take] %w to [initialization] %v : $*@sil_weak CP? - // CHECK: [[DEST_REF_ADDR:%.*]] = getelementptr inbounds { %swift.weak, i8** }, { %swift.weak, i8** }* [[V]], i32 0, i32 0 - // CHECK: [[SRC_REF_ADDR:%.*]] = getelementptr inbounds { %swift.weak, i8** }, { %swift.weak, i8** }* %0, i32 0, i32 0 - // CHECK: call %swift.weak* @swift_weakTakeAssign(%swift.weak* returned [[DEST_REF_ADDR]], %swift.weak* [[SRC_REF_ADDR]]) - // CHECK: [[SRC_WITNESS_ADDR:%.*]] = getelementptr inbounds { %swift.weak, i8** }, { %swift.weak, i8** }* %0, i32 0, i32 1 - // CHECK: [[WITNESS:%.*]] = load i8**, i8*** [[SRC_WITNESS_ADDR]], align 8 - // CHECK: [[DEST_WITNESS_ADDR:%.*]] = getelementptr inbounds { %swift.weak, i8** }, { %swift.weak, i8** }* [[V]], i32 0, i32 1 - // CHECK: store i8** [[WITNESS]], i8*** [[DEST_WITNESS_ADDR]], align 8 + // CHECK: call { %swift.weak, i8** }* @_T012existentials2CP_pSgXwWd({ %swift.weak, i8** }* %0, { %swift.weak, i8** }* [[V]]) copy_addr [take] %w to %v : $*@sil_weak CP? - // CHECK: [[DEST_REF_ADDR:%.*]] = getelementptr inbounds { %swift.weak, i8** }, { %swift.weak, i8** }* [[V]], i32 0, i32 0 - // CHECK: [[SRC_REF_ADDR:%.*]] = getelementptr inbounds { %swift.weak, i8** }, { %swift.weak, i8** }* %0, i32 0, i32 0 - // CHECK: call %swift.weak* @swift_weakCopyInit(%swift.weak* returned [[DEST_REF_ADDR]], %swift.weak* [[SRC_REF_ADDR]]) - // CHECK: [[SRC_WITNESS_ADDR:%.*]] = getelementptr inbounds { %swift.weak, i8** }, { %swift.weak, i8** }* %0, i32 0, i32 1 - // CHECK: [[WITNESS:%.*]] = load i8**, i8*** [[SRC_WITNESS_ADDR]], align 8 - // CHECK: [[DEST_WITNESS_ADDR:%.*]] = getelementptr inbounds { %swift.weak, i8** }, { %swift.weak, i8** }* [[V]], i32 0, i32 1 - // CHECK: store i8** [[WITNESS]], i8*** [[DEST_WITNESS_ADDR]], align 8 + // CHECK: call { %swift.weak, i8** }* @_T012existentials2CP_pSgXwWc({ %swift.weak, i8** }* %0, { %swift.weak, i8** }* [[V]]) copy_addr %w to [initialization] %v : $*@sil_weak CP? - // CHECK: [[DEST_REF_ADDR:%.*]] = getelementptr inbounds { %swift.weak, i8** }, { %swift.weak, i8** }* [[V]], i32 0, i32 0 - // CHECK: [[SRC_REF_ADDR:%.*]] = getelementptr inbounds { %swift.weak, i8** }, { %swift.weak, i8** }* %0, i32 0, i32 0 - // CHECK: call %swift.weak* @swift_weakCopyAssign(%swift.weak* returned [[DEST_REF_ADDR]], %swift.weak* [[SRC_REF_ADDR]]) - // CHECK: [[SRC_WITNESS_ADDR:%.*]] = getelementptr inbounds { %swift.weak, i8** }, { %swift.weak, i8** }* %0, i32 0, i32 1 - // CHECK: [[WITNESS:%.*]] = load i8**, i8*** [[SRC_WITNESS_ADDR]], align 8 - // CHECK: [[DEST_WITNESS_ADDR:%.*]] = getelementptr inbounds { %swift.weak, i8** }, { %swift.weak, i8** }* [[V]], i32 0, i32 1 - // CHECK: store i8** [[WITNESS]], i8*** [[DEST_WITNESS_ADDR]], align 8 + // CHECK: call { %swift.weak, i8** }* @_T012existentials2CP_pSgXwWf({ %swift.weak, i8** }* %0, { %swift.weak, i8** }* [[V]]) copy_addr %w to %v : $*@sil_weak CP? // CHECK: [[REF_ADDR:%.*]] = getelementptr inbounds { %swift.weak, i8** }, { %swift.weak, i8** }* [[V]], i32 0, i32 0 diff --git a/test/IRGen/existentials_objc.sil b/test/IRGen/existentials_objc.sil index 429894d063508..2c16ecc502e00 100644 --- a/test/IRGen/existentials_objc.sil +++ b/test/IRGen/existentials_objc.sil @@ -39,12 +39,16 @@ bb0(%0 : $*Any, %1 : $*Any): } // CHECK-DAG: define{{( protected)?}} swiftcc void @take_opaque_existential([[ANY:%Any]]* noalias nocapture sret, %Any* noalias nocapture dereferenceable({{.*}})) {{.*}} { -// CHECK: [[T0:%.*]] = getelementptr inbounds [[ANY]], [[ANY]]* [[SRC:%1]], i32 0, i32 1 +// CHECK: call %Any* @_T0ypWb(%Any* %1, %Any* %0) +// CHECK-NEXT: ret void + +// CHECK-DAG: define{{( protected)?}} linkonce_odr hidden %Any* @_T0ypWb([[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:%0]], i32 0, i32 1 +// 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* %1, i32 0, i32 0 -// CHECK-NEXT: [[TO_BUFFER_ADDR:%.*]] = getelementptr inbounds %Any, %Any* %0, i32 0, i32 0 +// 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]] @@ -52,7 +56,6 @@ bb0(%0 : $*Any, %1 : $*Any): // 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-NEXT: ret void // rdar://problem/19035529 @objc protocol OP {} @@ -135,40 +138,16 @@ entry(%w : $*@sil_weak CP?, %a : $CP?): // CHECK: [[DEST_WITNESS:%.*]] = load i8**, i8*** [[SRC_WITNESS_ADDR]] %c = load_weak %w : $*@sil_weak CP? - // CHECK: [[DEST_REF_ADDR:%.*]] = getelementptr inbounds { %swift.weak, i8** }, { %swift.weak, i8** }* [[V]], i32 0, i32 0 - // CHECK: [[SRC_REF_ADDR:%.*]] = getelementptr inbounds { %swift.weak, i8** }, { %swift.weak, i8** }* %0, i32 0, i32 0 - // CHECK: call %swift.weak* @swift_unknownWeakTakeInit(%swift.weak* returned [[DEST_REF_ADDR]], %swift.weak* [[SRC_REF_ADDR]]) - // CHECK: [[SRC_WITNESS_ADDR:%.*]] = getelementptr inbounds { %swift.weak, i8** }, { %swift.weak, i8** }* %0, i32 0, i32 1 - // CHECK: [[WITNESS:%.*]] = load i8**, i8*** [[SRC_WITNESS_ADDR]], align 8 - // CHECK: [[DEST_WITNESS_ADDR:%.*]] = getelementptr inbounds { %swift.weak, i8** }, { %swift.weak, i8** }* [[V]], i32 0, i32 1 - // CHECK: store i8** [[WITNESS]], i8*** [[DEST_WITNESS_ADDR]], align 8 + // CHECK: call { %swift.weak, i8** }* @_T017existentials_objc2CP_pSgXwWb({ %swift.weak, i8** }* %0, { %swift.weak, i8** }* [[V]]) copy_addr [take] %w to [initialization] %v : $*@sil_weak CP? - // CHECK: [[DEST_REF_ADDR:%.*]] = getelementptr inbounds { %swift.weak, i8** }, { %swift.weak, i8** }* [[V]], i32 0, i32 0 - // CHECK: [[SRC_REF_ADDR:%.*]] = getelementptr inbounds { %swift.weak, i8** }, { %swift.weak, i8** }* %0, i32 0, i32 0 - // CHECK: call %swift.weak* @swift_unknownWeakTakeAssign(%swift.weak* returned [[DEST_REF_ADDR]], %swift.weak* [[SRC_REF_ADDR]]) - // CHECK: [[SRC_WITNESS_ADDR:%.*]] = getelementptr inbounds { %swift.weak, i8** }, { %swift.weak, i8** }* %0, i32 0, i32 1 - // CHECK: [[WITNESS:%.*]] = load i8**, i8*** [[SRC_WITNESS_ADDR]], align 8 - // CHECK: [[DEST_WITNESS_ADDR:%.*]] = getelementptr inbounds { %swift.weak, i8** }, { %swift.weak, i8** }* [[V]], i32 0, i32 1 - // CHECK: store i8** [[WITNESS]], i8*** [[DEST_WITNESS_ADDR]], align 8 + // CHECK: call { %swift.weak, i8** }* @_T017existentials_objc2CP_pSgXwWd({ %swift.weak, i8** }* %0, { %swift.weak, i8** }* [[V]]) copy_addr [take] %w to %v : $*@sil_weak CP? - // CHECK: [[DEST_REF_ADDR:%.*]] = getelementptr inbounds { %swift.weak, i8** }, { %swift.weak, i8** }* [[V]], i32 0, i32 0 - // CHECK: [[SRC_REF_ADDR:%.*]] = getelementptr inbounds { %swift.weak, i8** }, { %swift.weak, i8** }* %0, i32 0, i32 0 - // CHECK: call %swift.weak* @swift_unknownWeakCopyInit(%swift.weak* returned [[DEST_REF_ADDR]], %swift.weak* [[SRC_REF_ADDR]]) - // CHECK: [[SRC_WITNESS_ADDR:%.*]] = getelementptr inbounds { %swift.weak, i8** }, { %swift.weak, i8** }* %0, i32 0, i32 1 - // CHECK: [[WITNESS:%.*]] = load i8**, i8*** [[SRC_WITNESS_ADDR]], align 8 - // CHECK: [[DEST_WITNESS_ADDR:%.*]] = getelementptr inbounds { %swift.weak, i8** }, { %swift.weak, i8** }* [[V]], i32 0, i32 1 - // CHECK: store i8** [[WITNESS]], i8*** [[DEST_WITNESS_ADDR]], align 8 + // CHECK: call { %swift.weak, i8** }* @_T017existentials_objc2CP_pSgXwWc({ %swift.weak, i8** }* %0, { %swift.weak, i8** }* [[V]]) copy_addr %w to [initialization] %v : $*@sil_weak CP? - // CHECK: [[DEST_REF_ADDR:%.*]] = getelementptr inbounds { %swift.weak, i8** }, { %swift.weak, i8** }* [[V]], i32 0, i32 0 - // CHECK: [[SRC_REF_ADDR:%.*]] = getelementptr inbounds { %swift.weak, i8** }, { %swift.weak, i8** }* %0, i32 0, i32 0 - // CHECK: call %swift.weak* @swift_unknownWeakCopyAssign(%swift.weak* returned [[DEST_REF_ADDR]], %swift.weak* [[SRC_REF_ADDR]]) - // CHECK: [[SRC_WITNESS_ADDR:%.*]] = getelementptr inbounds { %swift.weak, i8** }, { %swift.weak, i8** }* %0, i32 0, i32 1 - // CHECK: [[WITNESS:%.*]] = load i8**, i8*** [[SRC_WITNESS_ADDR]], align 8 - // CHECK: [[DEST_WITNESS_ADDR:%.*]] = getelementptr inbounds { %swift.weak, i8** }, { %swift.weak, i8** }* [[V]], i32 0, i32 1 - // CHECK: store i8** [[WITNESS]], i8*** [[DEST_WITNESS_ADDR]], align 8 + // CHECK: call { %swift.weak, i8** }* @_T017existentials_objc2CP_pSgXwWf({ %swift.weak, i8** }* %0, { %swift.weak, i8** }* [[V]]) copy_addr %w to %v : $*@sil_weak CP? // CHECK: [[REF_ADDR:%.*]] = getelementptr inbounds { %swift.weak, i8** }, { %swift.weak, i8** }* [[V]], i32 0, i32 0 diff --git a/test/IRGen/existentials_opaque_boxed.sil b/test/IRGen/existentials_opaque_boxed.sil index 379b50a2bbfef..9d1f5a7800737 100644 --- a/test/IRGen/existentials_opaque_boxed.sil +++ b/test/IRGen/existentials_opaque_boxed.sil @@ -432,23 +432,7 @@ bb0(%0 : $*Existential): // CHECK: define{{( protected)?}} swiftcc void @test_assignWithTake_existential_addr(%T25existentials_opaque_boxed11ExistentialP* // CHECK: [[ALLOCA:%.*]] = alloca %T25existentials_opaque_boxed11ExistentialP // CHECK: call void @__swift_destroy_boxed_opaque_existential_1(%T25existentials_opaque_boxed11ExistentialP* [[ALLOCA]]) -// CHECK: [[ARG_TYPE_ADDR:%.*]] = getelementptr inbounds %T25existentials_opaque_boxed11ExistentialP, %T25existentials_opaque_boxed11ExistentialP* %0, i32 0, i32 1 -// CHECK: [[ARG_TYPE:%.*]] = load %swift.type*, %swift.type** [[ARG_TYPE_ADDR]] -// CHECK: [[LOCAL_TYPE_ADDR:%.*]] = getelementptr inbounds %T25existentials_opaque_boxed11ExistentialP, %T25existentials_opaque_boxed11ExistentialP* [[ALLOCA]], i32 0, i32 1 -// CHECK: store %swift.type* [[ARG_TYPE]], %swift.type** [[LOCAL_TYPE_ADDR]] -// CHECK: [[ARG_PWT_ADDR:%.*]] = getelementptr inbounds %T25existentials_opaque_boxed11ExistentialP, %T25existentials_opaque_boxed11ExistentialP* %0, i32 0, i32 2 -// CHECK: [[ARG_PWT:%.*]] = load i8**, i8*** [[ARG_PWT_ADDR]] -// CHECK: [[LOCAL_PWT_ADDR:%.*]] = getelementptr inbounds %T25existentials_opaque_boxed11ExistentialP, %T25existentials_opaque_boxed11ExistentialP* [[ALLOCA]], i32 0, i32 2 -// CHECK: store i8** [[ARG_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* [[ALLOCA]], i32 0, i32 0 -// CHECK: [[CAST_ADDR:%.*]] = bitcast %swift.type* [[ARG_TYPE]] 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* [[ARG_TYPE]]) +// CHECK: call %T25existentials_opaque_boxed11ExistentialP* @_T025existentials_opaque_boxed11Existential_pWb(%T25existentials_opaque_boxed11ExistentialP* %0, %T25existentials_opaque_boxed11ExistentialP* [[ALLOCA]]) // CHECK: ret void sil @test_assignWithTake_existential_addr : $@convention(thin) (@in Existential) -> () { bb0(%0 : $*Existential): @@ -459,25 +443,29 @@ bb0(%0 : $*Existential): return %t : $() } -// CHECK: define{{( protected)?}} swiftcc void @test_initWithTake_existential_addr(%T25existentials_opaque_boxed11ExistentialP* -// CHECK: [[LOCAL:%.*]] = alloca %T25existentials_opaque_boxed11ExistentialP +// CHECK: define{{( protected)?}} linkonce_odr hidden %T25existentials_opaque_boxed11ExistentialP* @_T025existentials_opaque_boxed11Existential_pWb(%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* [[LOCAL]], i32 0, i32 1 +// 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* [[LOCAL]], i32 0, i32 2 +// 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* [[ALLOCA]], i32 0, i32 0 -// CHECK: [[CAST_ADDR:%.*]] = bitcast %swift.type* [[ARG_TYPE]] to i8*** +// 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* [[ARG_TYPE]]) +// CHECK: call %swift.opaque* [[INITWITHTAKEBUFFER]]({{.*}} [[BUFFER_LOCAL_ADDR]], {{.*}} [[BUFFER_ARG_ADDR]], %swift.type* [[METADATA]]) +// CHECK: ret %T25existentials_opaque_boxed11ExistentialP* %1 + +// CHECK: define{{( protected)?}} swiftcc void @test_initWithTake_existential_addr(%T25existentials_opaque_boxed11ExistentialP* +// CHECK: [[LOCAL:%.*]] = alloca %T25existentials_opaque_boxed11ExistentialP +// CHECK: call %T25existentials_opaque_boxed11ExistentialP* @_T025existentials_opaque_boxed11Existential_pWb(%T25existentials_opaque_boxed11ExistentialP* %0, %T25existentials_opaque_boxed11ExistentialP* [[LOCAL]]) // CHECK: ret void sil @test_initWithTake_existential_addr : $@convention(thin) (@in Existential) -> () { bb0(%0 : $*Existential): @@ -490,23 +478,26 @@ bb0(%0 : $*Existential): // CHECK-LABEL: define{{( protected)?}} swiftcc void @test_initWithCopy_existential_addr(%T25existentials_opaque_boxed11ExistentialP* // CHECK: [[LOCAL:%.*]] = alloca %T25existentials_opaque_boxed11ExistentialP +// CHECK: call %T25existentials_opaque_boxed11ExistentialP* @_T025existentials_opaque_boxed11Existential_pWc(%T25existentials_opaque_boxed11ExistentialP* %0, %T25existentials_opaque_boxed11ExistentialP* [[LOCAL]]) +// CHECK: ret void +// CHECK-LABEL: define{{( protected)?}} linkonce_odr hidden %T25existentials_opaque_boxed11ExistentialP* @_T025existentials_opaque_boxed11Existential_pWc(%T25existentials_opaque_boxed11ExistentialP*, %T25existentials_opaque_boxed11ExistentialP*) // CHECK: [[TYPE_ADDR:%.*]] = getelementptr inbounds %T25existentials_opaque_boxed11ExistentialP, %T25existentials_opaque_boxed11ExistentialP* %0, i32 0, i32 1 -// CHECK: [[TYPE:%.*]] = load %swift.type*, %swift.type** [[TYPE_ADDR]] -// CHECK: [[LOCAL_TYPE_ADDR:%.*]] = getelementptr inbounds %T25existentials_opaque_boxed11ExistentialP, %T25existentials_opaque_boxed11ExistentialP* [[LOCAL]], i32 0, i32 1 -// CHECK: store %swift.type* [[TYPE]], %swift.type** [[LOCAL_TYPE_ADDR]] +// CHECK: [[ARG_TYPE:%.*]] = load %swift.type*, %swift.type** [[TYPE_ADDR]] +// CHECK: [[LOCAL_TYPE_ADDR:%.*]] = getelementptr inbounds %T25existentials_opaque_boxed11ExistentialP, %T25existentials_opaque_boxed11ExistentialP* %1, i32 0, i32 1 +// CHECK: store %swift.type* [[ARG_TYPE]], %swift.type** [[LOCAL_TYPE_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* [[LOCAL]], i32 0, i32 2 +// 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* [[ALLOCA]], 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* [[ARG_TYPE]] to i8*** // CHECK: [[VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[CAST_ADDR]], {{(i64|i32)}} -1 // CHECK: [[VWT:%.*]] = load i8**, i8*** [[VWT_ADDR]] // CHECK: [[VW:%.*]] = load i8*, i8** [[VWT]] // CHECK: [[INITWITHCOPYBUFFER:%.*]] = bitcast i8* [[VW]] // CHECK: call %swift.opaque* [[INITWITHCOPYBUFFER]]({{.*}} noalias [[BUFFER_LOCAL_ADDR]], {{.*}} noalias [[BUFFER_ARG_ADDR]], %swift.type* [[ARG_TYPE]]) -// CHECK: ret void +// CHECK: ret %T25existentials_opaque_boxed11ExistentialP* %1 sil @test_initWithCopy_existential_addr : $@convention(thin) (@in Existential) -> () { bb0(%0 : $*Existential): %s = alloc_stack $Existential diff --git a/test/IRGen/unowned_objc.sil b/test/IRGen/unowned_objc.sil index 879d6834e4559..96d788e220193 100644 --- a/test/IRGen/unowned_objc.sil +++ b/test/IRGen/unowned_objc.sil @@ -61,13 +61,7 @@ bb0(%p : $P, %q : $P): // CHECK-NEXT: call %swift.unowned* @swift_unknownUnownedInit(%swift.unowned* returned [[T0]], [[UNKNOWN]]* [[PV:%0]]) store_unowned %p to [initialization] %x : $*@sil_unowned P - // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[UREF]], [[UREF]]* [[Y]], i32 0, i32 0 - // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[UREF]], [[UREF]]* [[X]], i32 0, i32 0 - // CHECK-NEXT: call %swift.unowned* @swift_unknownUnownedCopyInit(%swift.unowned* returned [[T0]], %swift.unowned* [[T1]]) - // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[UREF]], [[UREF]]* [[X]], i32 0, i32 1 - // CHECK-NEXT: [[WT:%.*]] = load i8**, i8*** [[T0]], align 8 - // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[UREF]], [[UREF]]* [[Y]], i32 0, i32 1 - // CHECK-NEXT: store i8** [[WT]], i8*** [[T0]], align 8 + // CHECK-NEXT: call { %swift.unowned, i8** }* @_T012unowned_objc1P_pXoWc({ %swift.unowned, i8** }* [[X]], { %swift.unowned, i8** }* [[Y]]) copy_addr %x to [initialization] %y : $*@sil_unowned P // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[UREF]], [[UREF]]* [[X]], i32 0, i32 0 @@ -79,13 +73,7 @@ bb0(%p : $P, %q : $P): // CHECK-NEXT: call void @swift_unknownRelease([[UNKNOWN]]* [[TV]]) strong_release %t0 : $P - // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[UREF]], [[UREF]]* [[Y]], i32 0, i32 0 - // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[UREF]], [[UREF]]* [[X]], i32 0, i32 0 - // CHECK-NEXT: call %swift.unowned* @swift_unknownUnownedCopyAssign(%swift.unowned* returned [[T0]], %swift.unowned* [[T1]]) - // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[UREF]], [[UREF]]* [[X]], i32 0, i32 1 - // CHECK-NEXT: [[WT:%.*]] = load i8**, i8*** [[T0]], align 8 - // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[UREF]], [[UREF]]* [[Y]], i32 0, i32 1 - // CHECK-NEXT: store i8** [[WT]], i8*** [[T0]], align 8 + // CHECK-NEXT: call { %swift.unowned, i8** }* @_T012unowned_objc1P_pXoWf({ %swift.unowned, i8** }* [[X]], { %swift.unowned, i8** }* [[Y]]) copy_addr %x to %y : $*@sil_unowned P // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[UREF]], [[UREF]]* [[Y]], i32 0, i32 1 @@ -94,22 +82,10 @@ bb0(%p : $P, %q : $P): // CHECK-NEXT: call %swift.unowned* @swift_unknownUnownedAssign(%swift.unowned* returned [[T0]], [[UNKNOWN]]* [[QV:%2]]) store_unowned %q to %y : $*@sil_unowned P - // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[UREF]], [[UREF]]* [[Y]], i32 0, i32 0 - // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[UREF]], [[UREF]]* [[X]], i32 0, i32 0 - // CHECK-NEXT: call %swift.unowned* @swift_unknownUnownedTakeAssign(%swift.unowned* returned [[T0]], %swift.unowned* [[T1]]) - // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[UREF]], [[UREF]]* [[X]], i32 0, i32 1 - // CHECK-NEXT: [[WT:%.*]] = load i8**, i8*** [[T0]], align 8 - // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[UREF]], [[UREF]]* [[Y]], i32 0, i32 1 - // CHECK-NEXT: store i8** [[WT]], i8*** [[T0]], align 8 + // CHECK-NEXT: call { %swift.unowned, i8** }* @_T012unowned_objc1P_pXoWd({ %swift.unowned, i8** }* [[X]], { %swift.unowned, i8** }* [[Y]]) copy_addr [take] %x to %y : $*@sil_unowned P - // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[UREF]], [[UREF]]* [[X]], i32 0, i32 0 - // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[UREF]], [[UREF]]* [[Y]], i32 0, i32 0 - // CHECK-NEXT: call %swift.unowned* @swift_unknownUnownedTakeInit(%swift.unowned* returned [[T0]], %swift.unowned* [[T1]]) - // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[UREF]], [[UREF]]* [[Y]], i32 0, i32 1 - // CHECK-NEXT: [[WT:%.*]] = load i8**, i8*** [[T0]], align 8 - // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[UREF]], [[UREF]]* [[X]], i32 0, i32 1 - // CHECK-NEXT: store i8** [[WT]], i8*** [[T0]], align 8 + // CHECK-NEXT: call { %swift.unowned, i8** }* @_T012unowned_objc1P_pXoWb({ %swift.unowned, i8** }* [[Y]], { %swift.unowned, i8** }* [[X]]) copy_addr [take] %y to [initialization] %x : $*@sil_unowned P // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[UREF]], [[UREF]]* [[Y]], i32 0, i32 0