diff --git a/docs/ABI.rst b/docs/ABI.rst index 082f507ec4663..efb07219ad354 100644 --- a/docs/ABI.rst +++ b/docs/ABI.rst @@ -792,6 +792,9 @@ Globals global ::= type 'WV' // value witness table global ::= entity 'Wv' DIRECTNESS // field offset + global ::= type 'Wy' // Outlined Copy Function Type + global ::= type 'We' // Outlined Consume Function Type + DIRECTNESS ::= 'd' // direct DIRECTNESS ::= 'i' // indirect diff --git a/include/swift/Basic/DemangleNodes.def b/include/swift/Basic/DemangleNodes.def index 3c32c40357b81..a9bfb8bf80e75 100644 --- a/include/swift/Basic/DemangleNodes.def +++ b/include/swift/Basic/DemangleNodes.def @@ -177,5 +177,7 @@ NODE(ThrowsAnnotation) NODE(EmptyList) NODE(FirstElementMarker) NODE(VariadicMarker) +NODE(OutlinedCopy) +NODE(OutlinedConsume) #undef CONTEXT_NODE #undef NODE diff --git a/lib/Basic/Demangle.cpp b/lib/Basic/Demangle.cpp index e92f7d5effcb4..e7de1579fe8fa 100644 --- a/lib/Basic/Demangle.cpp +++ b/lib/Basic/Demangle.cpp @@ -2544,6 +2544,8 @@ class NodePrinter { case Node::Kind::EmptyList: case Node::Kind::FirstElementMarker: case Node::Kind::VariadicMarker: + case Node::Kind::OutlinedCopy: + case Node::Kind::OutlinedConsume: return false; } unreachable("bad node kind"); @@ -2975,6 +2977,14 @@ void NodePrinter::print(NodePointer pointer, bool asContext, bool suppressType) Printer << "curry thunk of "; print(pointer->getChild(0), asContext, suppressType); return; + case Node::Kind::OutlinedCopy: + Printer << "outlined copy of "; + print(pointer->getChild(0), asContext, suppressType); + return; + case Node::Kind::OutlinedConsume: + Printer << "outlined consume of "; + print(pointer->getChild(0), asContext, suppressType); + return; case Node::Kind::Directness: Printer << toString(Directness(pointer->getIndex())) << " "; return; diff --git a/lib/Basic/Demangler.cpp b/lib/Basic/Demangler.cpp index bc6ba760953d2..45eefa586740a 100644 --- a/lib/Basic/Demangler.cpp +++ b/lib/Basic/Demangler.cpp @@ -1320,6 +1320,14 @@ NodePointer Demangler::demangleWitness() { return createWithChildren(Node::Kind::AssociatedTypeWitnessTableAccessor, Conf, Name, ProtoTy); } + case 'y': { + return createWithChild(Node::Kind::OutlinedCopy, + popNode(Node::Kind::Type)); + } + case 'e': { + return createWithChild(Node::Kind::OutlinedConsume, + popNode(Node::Kind::Type)); + } default: return nullptr; } diff --git a/lib/Basic/Remangle.cpp b/lib/Basic/Remangle.cpp index 676ec845e20e1..65b37a11b99f3 100644 --- a/lib/Basic/Remangle.cpp +++ b/lib/Basic/Remangle.cpp @@ -1697,6 +1697,16 @@ void Remangler::mangleVariadicMarker(Node *node) { Out << ""; } +void Remangler::mangleOutlinedCopy(Node *node) { + Out << "Wy"; + mangleChildNodes(node); +} + +void Remangler::mangleOutlinedConsume(Node *node) { + Out << "We"; + mangleChildNodes(node); +} + void Remangler::mangleSILBoxTypeWithLayout(Node *node) { assert(node->getKind() == Node::Kind::SILBoxTypeWithLayout); assert(node->getNumChildren() == 1 || node->getNumChildren() == 3); diff --git a/lib/Basic/Remangler.cpp b/lib/Basic/Remangler.cpp index cbc1450669c02..88ee5d765a712 100644 --- a/lib/Basic/Remangler.cpp +++ b/lib/Basic/Remangler.cpp @@ -1626,6 +1626,16 @@ void Remangler::mangleVariadicMarker(Node *node) { Buffer << 'd'; } +void Remangler::mangleOutlinedCopy(Node *node) { + mangleSingleChildNode(node); + Buffer << "Wy"; +} + +void Remangler::mangleOutlinedConsume(Node *node) { + mangleSingleChildNode(node); + Buffer << "We"; +} + void Remangler::mangleSILBoxTypeWithLayout(Node *node) { assert(node->getNumChildren() == 1 || node->getNumChildren() == 3); assert(node->getChild(0)->getKind() == Node::Kind::SILBoxLayout); diff --git a/lib/IRGen/GenEnum.cpp b/lib/IRGen/GenEnum.cpp index ed0132a893114..202e1032ad562 100644 --- a/lib/IRGen/GenEnum.cpp +++ b/lib/IRGen/GenEnum.cpp @@ -117,6 +117,7 @@ #include "GenProto.h" #include "GenType.h" #include "IRGenDebugInfo.h" +#include "IRGenMangler.h" #include "IRGenModule.h" #include "LoadableTypeInfo.h" #include "NonFixedTypeInfo.h" @@ -1338,6 +1339,20 @@ namespace { llvm::Value *extraTag = ExtraTagBitCount > 0 ? src.claimNext() : nullptr; return {payload, extraTag}; } + std::pair + getPayloadAndExtraTagFromExplosionOutlined(IRGenFunction &IGF, + Explosion &src) const { + EnumPayload payload; + unsigned claimSZ = src.size(); + if (ExtraTagBitCount > 0) { + --claimSZ; + } + for (unsigned i = 0; i < claimSZ; ++i) { + payload.PayloadValues.push_back(src.claimNext()); + } + llvm::Value *extraTag = ExtraTagBitCount > 0 ? src.claimNext() : nullptr; + return {payload, extraTag}; + } std::pair emitPrimitiveLoadPayloadAndExtraTag(IRGenFunction &IGF, Address addr) const{ @@ -1385,6 +1400,27 @@ namespace { } }; + static void computePayloadTypesAndTagType( + IRGenModule &IGM, const TypeInfo &TI, + SmallVector &PayloadTypesAndTagType) { + for (auto &element : TI.getSchema()) { + auto type = element.getScalarType(); + PayloadTypesAndTagType.push_back(type); + } + } + + static llvm::Function *createOutlineLLVMFunction( + IRGenModule &IGM, std::string &name, + SmallVector &PayloadTypesAndTagType) { + auto consumeTy = llvm::FunctionType::get(IGM.VoidTy, PayloadTypesAndTagType, + /*isVarArg*/ false); + auto func = + llvm::Function::Create(consumeTy, llvm::GlobalValue::InternalLinkage, + llvm::StringRef(name), IGM.getModule()); + func->setAttributes(IGM.constructInitialAttributes()); + return func; + } + class SinglePayloadEnumImplStrategy final : public PayloadEnumImplStrategyBase { @@ -1436,6 +1472,74 @@ namespace { unsigned NumExtraInhabitantTagValues = ~0U; + llvm::Function *copyEnumFunction = nullptr; + llvm::Function *consumeEnumFunction = nullptr; + SmallVector PayloadTypesAndTagType; + + llvm::Function *emitCopyEnumFunction(IRGenModule &IGM, EnumDecl *theEnum) { + IRGenMangler Mangler; + std::string name = Mangler.mangleOutlinedCopyFunction(theEnum); + auto func = createOutlineLLVMFunction(IGM, name, PayloadTypesAndTagType); + + IRGenFunction IGF(IGM, func); + Explosion src = IGF.collectParameters(); + + EnumPayload payload; + llvm::Value *extraTag; + std::tie(payload, extraTag) = + getPayloadAndExtraTagFromExplosionOutlined(IGF, src); + llvm::BasicBlock *endBB = + testFixedEnumContainsPayload(IGF, payload, extraTag); + + if (PayloadBitCount > 0) { + ConditionalDominanceScope condition(IGF); + Explosion payloadValue; + Explosion payloadCopy; + auto &loadableTI = getLoadablePayloadTypeInfo(); + loadableTI.unpackFromEnumPayload(IGF, payload, payloadValue, 0); + loadableTI.copy(IGF, payloadValue, payloadCopy, Atomicity::Atomic); + payloadCopy.claimAll(); // FIXME: repack if not bit-identical + } + + IGF.Builder.CreateBr(endBB); + IGF.Builder.emitBlock(endBB); + + IGF.Builder.CreateRetVoid(); + return func; + } + + llvm::Function *emitConsumeEnumFunction(IRGenModule &IGM, + EnumDecl *theEnum) { + IRGenMangler Mangler; + std::string name = Mangler.mangleOutlinedConsumeFunction(theEnum); + auto func = createOutlineLLVMFunction(IGM, name, PayloadTypesAndTagType); + + IRGenFunction IGF(IGM, func); + Explosion src = IGF.collectParameters(); + + EnumPayload payload; + llvm::Value *extraTag; + std::tie(payload, extraTag) = + getPayloadAndExtraTagFromExplosionOutlined(IGF, src); + llvm::BasicBlock *endBB = + testFixedEnumContainsPayload(IGF, payload, extraTag); + + // If we did, consume it. + if (PayloadBitCount > 0) { + ConditionalDominanceScope condition(IGF); + Explosion payloadValue; + auto &loadableTI = getLoadablePayloadTypeInfo(); + loadableTI.unpackFromEnumPayload(IGF, payload, payloadValue, 0); + loadableTI.consume(IGF, payloadValue, Atomicity::Atomic); + } + + IGF.Builder.CreateBr(endBB); + IGF.Builder.emitBlock(endBB); + + IGF.Builder.CreateRetVoid(); + return func; + } + static EnumPayloadSchema getPreferredPayloadSchema(Element payloadElement) { // TODO: If the payload type info provides a preferred explosion schema, // use it. For now, just use a generic word-chunked schema. @@ -2130,6 +2234,18 @@ namespace { } } + void fillExplosionForOutlinedCall(IRGenFunction &IGF, Explosion &src, + Explosion &out) const { + assert(out.empty() && "Out explosion must be empty!"); + EnumPayload payload; + llvm::Value *extraTag; + std::tie(payload, extraTag) = + getPayloadAndExtraTagFromExplosion(IGF, src); + payload.explode(IGF.IGM, out); + if (extraTag) + out.add(extraTag); + } + public: void copy(IRGenFunction &IGF, Explosion &src, Explosion &dest, Atomicity atomicity) const override { @@ -2141,37 +2257,22 @@ namespace { return; case Normal: { - // Copy the payload, if we have it. - EnumPayload payload; llvm::Value *extraTag; - std::tie(payload, extraTag) - = getPayloadAndExtraTagFromExplosion(IGF, src); - - llvm::BasicBlock *endBB = testFixedEnumContainsPayload(IGF, payload, extraTag); - - if (PayloadBitCount > 0) { - ConditionalDominanceScope condition(IGF); - Explosion payloadValue; - Explosion payloadCopy; - auto &loadableTI = getLoadablePayloadTypeInfo(); - loadableTI.unpackFromEnumPayload(IGF, payload, payloadValue, 0); - loadableTI.copy(IGF, payloadValue, payloadCopy, Atomicity::Atomic); - payloadCopy.claimAll(); // FIXME: repack if not bit-identical - } - - IGF.Builder.CreateBr(endBB); - IGF.Builder.emitBlock(endBB); - + assert(copyEnumFunction && "Did not create copy function for enum"); + Explosion tmp; + fillExplosionForOutlinedCall(IGF, src, tmp); + llvm::CallInst *call = + IGF.Builder.CreateCall(copyEnumFunction, tmp.getAll()); + call->setCallingConv(IGF.IGM.DefaultCC); // Copy to the new explosion. - payload.explode(IGF.IGM, dest); - if (extraTag) dest.add(extraTag); + dest.add(tmp.claimAll()); return; } case NullableRefcounted: { // Bitcast to swift.refcounted*, and retain the pointer. llvm::Value *val = src.claimNext(); - llvm::Value *ptr = IGF.Builder.CreateBitOrPointerCast(val, - getRefcountedPtrType(IGF.IGM)); + llvm::Value *ptr = IGF.Builder.CreateBitOrPointerCast( + val, getRefcountedPtrType(IGF.IGM)); retainRefcountedPayload(IGF, ptr); dest.add(val); return; @@ -2189,38 +2290,25 @@ namespace { return; case Normal: { - // Check that we have a payload. - EnumPayload payload; llvm::Value *extraTag; - std::tie(payload, extraTag) - = getPayloadAndExtraTagFromExplosion(IGF, src); - - llvm::BasicBlock *endBB - = testFixedEnumContainsPayload(IGF, payload, extraTag); - - // If we did, consume it. - if (PayloadBitCount > 0) { - ConditionalDominanceScope condition(IGF); - Explosion payloadValue; - auto &loadableTI = getLoadablePayloadTypeInfo(); - loadableTI.unpackFromEnumPayload(IGF, payload, payloadValue, 0); - loadableTI.consume(IGF, payloadValue, Atomicity::Atomic); - } - - IGF.Builder.CreateBr(endBB); - IGF.Builder.emitBlock(endBB); + assert(consumeEnumFunction && + "Did not create consume function for enum"); + Explosion tmp; + fillExplosionForOutlinedCall(IGF, src, tmp); + llvm::CallInst *call = + IGF.Builder.CreateCall(consumeEnumFunction, tmp.claimAll()); + call->setCallingConv(IGF.IGM.DefaultCC); return; } case NullableRefcounted: { // Bitcast to swift.refcounted*, and hand to swift_release. llvm::Value *val = src.claimNext(); - llvm::Value *ptr = IGF.Builder.CreateBitOrPointerCast(val, - getRefcountedPtrType(IGF.IGM)); + llvm::Value *ptr = IGF.Builder.CreateBitOrPointerCast( + val, getRefcountedPtrType(IGF.IGM)); releaseRefcountedPayload(IGF, ptr); return; } } - } void fixLifetime(IRGenFunction &IGF, Explosion &src) const override { @@ -2802,6 +2890,59 @@ namespace { ReferenceCounting Refcounting; bool AllowFixedLayoutOptimizations; + llvm::Function *copyEnumFunction = nullptr; + llvm::Function *consumeEnumFunction = nullptr; + SmallVector PayloadTypesAndTagType; + + llvm::Function *emitCopyEnumFunction(IRGenModule &IGM, EnumDecl *theEnum) { + IRGenMangler Mangler; + std::string name = Mangler.mangleOutlinedCopyFunction(theEnum); + auto func = createOutlineLLVMFunction(IGM, name, PayloadTypesAndTagType); + + IRGenFunction IGF(IGM, func); + Explosion src = IGF.collectParameters(); + + auto parts = destructureAndTagLoadableEnumFromOutlined(IGF, src); + + forNontrivialPayloads(IGF, parts.tag, [&](unsigned tagIndex, + EnumImplStrategy::Element elt) { + auto <i = cast(*elt.ti); + Explosion value; + projectPayloadValue(IGF, parts.payload, tagIndex, lti, value); + + Explosion tmp; + lti.copy(IGF, value, tmp, Atomicity::Atomic); + tmp.claimAll(); // FIXME: repack if not bit-identical + }); + + IGF.Builder.CreateRetVoid(); + return func; + } + + llvm::Function *emitConsumeEnumFunction(IRGenModule &IGM, + EnumDecl *theEnum) { + IRGenMangler Mangler; + std::string name = Mangler.mangleOutlinedCopyFunction(theEnum); + auto func = createOutlineLLVMFunction(IGM, name, PayloadTypesAndTagType); + + IRGenFunction IGF(IGM, func); + Explosion src = IGF.collectParameters(); + + auto parts = destructureAndTagLoadableEnumFromOutlined(IGF, src); + + forNontrivialPayloads(IGF, parts.tag, [&](unsigned tagIndex, + EnumImplStrategy::Element elt) { + auto <i = cast(*elt.ti); + Explosion value; + projectPayloadValue(IGF, parts.payload, tagIndex, lti, value); + + lti.consume(IGF, value, Atomicity::Atomic); + }); + + IGF.Builder.CreateRetVoid(); + return func; + } + static EnumPayloadSchema getPayloadSchema(ArrayRef payloads) { // TODO: We might be able to form a nicer schema if the payload elements // share a schema. For now just use a generic schema. @@ -3066,6 +3207,22 @@ namespace { return {destructured.payload, destructured.extraTagBits, tag}; } + DestructuredAndTaggedLoadableEnum + destructureAndTagLoadableEnumFromOutlined(IRGenFunction &IGF, + Explosion &src) const { + EnumPayload payload; + unsigned claimSZ = src.size(); + if (ExtraTagBitCount > 0) { + --claimSZ; + } + for (unsigned i = 0; i < claimSZ; ++i) { + payload.PayloadValues.push_back(src.claimNext()); + } + llvm::Value *extraTagBits = + ExtraTagBitCount > 0 ? src.claimNext() : nullptr; + llvm::Value *tag = extractPayloadTag(IGF, payload, extraTagBits); + return {payload, extraTagBits, tag}; + } /// Returns a tag index in the range [0..NumElements-1]. llvm::Value * @@ -3729,7 +3886,16 @@ namespace { APInt mask = ~PayloadTagBits.asAPInt(); payload.emitApplyAndMask(IGF, mask); } - + + void fillExplosionForOutlinedCall(IRGenFunction &IGF, Explosion &src, + Explosion &out) const { + assert(out.empty() && "Out explosion must be empty!"); + auto parts = destructureAndTagLoadableEnum(IGF, src); + parts.payload.explode(IGF.IGM, out); + if (parts.extraTagBits) + out.add(parts.extraTagBits); + } + public: void emitValueInjection(IRGenFunction &IGF, EnumElementDecl *elt, @@ -3762,25 +3928,15 @@ namespace { case BitwiseTakable: case Normal: { - auto parts = destructureAndTagLoadableEnum(IGF, src); - - forNontrivialPayloads(IGF, parts.tag, - [&](unsigned tagIndex, EnumImplStrategy::Element elt) { - auto <i = cast(*elt.ti); - Explosion value; - projectPayloadValue(IGF, parts.payload, tagIndex, lti, value); - - Explosion tmp; - lti.copy(IGF, value, tmp, Atomicity::Atomic); - tmp.claimAll(); // FIXME: repack if not bit-identical - }); - - parts.payload.explode(IGF.IGM, dest); - if (parts.extraTagBits) - dest.add(parts.extraTagBits); + assert(copyEnumFunction && "Did not create copy function for enum"); + Explosion tmp; + fillExplosionForOutlinedCall(IGF, src, tmp); + llvm::CallInst *call = + IGF.Builder.CreateCall(copyEnumFunction, tmp.getAll()); + call->setCallingConv(IGF.IGM.DefaultCC); + dest.add(tmp.claimAll()); return; } - case TaggedRefcounted: { auto parts = destructureLoadableEnum(IGF, src); @@ -3791,8 +3947,8 @@ namespace { maskTagBitsFromPayload(IGF, parts.payload); // Retain the pointer. - auto ptr = parts.payload.extractValue(IGF, - getRefcountedPtrType(IGF.IGM), 0); + auto ptr = + parts.payload.extractValue(IGF, getRefcountedPtrType(IGF.IGM), 0); retainRefcountedPayload(IGF, ptr); origPayload.explode(IGF.IGM, dest); @@ -3801,13 +3957,11 @@ namespace { return; } } - } void consume(IRGenFunction &IGF, Explosion &src, Atomicity atomicity) const override { assert(TIK >= Loadable); - switch (CopyDestroyKind) { case POD: src.claim(getExplosionSize()); @@ -3815,27 +3969,23 @@ namespace { case BitwiseTakable: case Normal: { - auto parts = destructureAndTagLoadableEnum(IGF, src); - - forNontrivialPayloads(IGF, parts.tag, - [&](unsigned tagIndex, EnumImplStrategy::Element elt) { - auto <i = cast(*elt.ti); - Explosion value; - projectPayloadValue(IGF, parts.payload, tagIndex, lti, value); - - lti.consume(IGF, value, Atomicity::Atomic); - }); + assert(consumeEnumFunction && + "Did not create consume function for enum"); + Explosion tmp; + fillExplosionForOutlinedCall(IGF, src, tmp); + llvm::CallInst *call = + IGF.Builder.CreateCall(consumeEnumFunction, tmp.claimAll()); + call->setCallingConv(IGF.IGM.DefaultCC); return; } - case TaggedRefcounted: { auto parts = destructureLoadableEnum(IGF, src); // Mask the tag bits out of the payload, if any. maskTagBitsFromPayload(IGF, parts.payload); - + // Release the pointer. - auto ptr = parts.payload.extractValue(IGF, - getRefcountedPtrType(IGF.IGM), 0); + auto ptr = + parts.payload.extractValue(IGF, getRefcountedPtrType(IGF.IGM), 0); releaseRefcountedPayload(IGF, ptr); return; } @@ -5376,11 +5526,18 @@ TypeInfo *SinglePayloadEnumImplStrategy::completeFixedLayout( auto alignment = payloadTI.getFixedAlignment(); applyLayoutAttributes(TC.IGM, Type.getSwiftRValueType(), /*fixed*/true, alignment); - - return getFixedEnumTypeInfo(enumTy, Size(sizeWithTag), std::move(spareBits), - alignment, - payloadTI.isPOD(ResilienceExpansion::Maximal), - payloadTI.isBitwiseTakable(ResilienceExpansion::Maximal)); + + getFixedEnumTypeInfo( + enumTy, Size(sizeWithTag), std::move(spareBits), alignment, + payloadTI.isPOD(ResilienceExpansion::Maximal), + payloadTI.isBitwiseTakable(ResilienceExpansion::Maximal)); + if (TIK >= Loadable && CopyDestroyKind == Normal) { + computePayloadTypesAndTagType(TC.IGM, *TI, PayloadTypesAndTagType); + copyEnumFunction = emitCopyEnumFunction(TC.IGM, theEnum); + consumeEnumFunction = emitConsumeEnumFunction(TC.IGM, theEnum); + } + + return const_cast(TI); } TypeInfo *SinglePayloadEnumImplStrategy::completeDynamicLayout( @@ -5561,8 +5718,16 @@ MultiPayloadEnumImplStrategy::completeFixedLayout(TypeConverter &TC, applyLayoutAttributes(TC.IGM, Type.getSwiftRValueType(), /*fixed*/ true, worstAlignment); - return getFixedEnumTypeInfo(enumTy, Size(sizeWithTag), std::move(spareBits), - worstAlignment, isPOD, isBT); + getFixedEnumTypeInfo(enumTy, Size(sizeWithTag), std::move(spareBits), + worstAlignment, isPOD, isBT); + if (TIK >= Loadable && + (CopyDestroyKind == Normal || CopyDestroyKind == BitwiseTakable)) { + computePayloadTypesAndTagType(TC.IGM, *TI, PayloadTypesAndTagType); + copyEnumFunction = emitCopyEnumFunction(TC.IGM, theEnum); + consumeEnumFunction = emitConsumeEnumFunction(TC.IGM, theEnum); + } + + return const_cast(TI); } diff --git a/lib/IRGen/IRBuilder.h b/lib/IRGen/IRBuilder.h index b91cf4aa6f6d8..db6c694605043 100644 --- a/lib/IRGen/IRBuilder.h +++ b/lib/IRGen/IRBuilder.h @@ -268,7 +268,8 @@ class IRBuilder : public IRBuilderBase { llvm::CallInst *CreateCall(llvm::Value *Callee, ArrayRef Args, const Twine &Name = "", llvm::MDNode *FPMathTag = nullptr) { - assert((!DebugInfo || getCurrentDebugLocation()) && "no debugloc on call"); + // assert((!DebugInfo || getCurrentDebugLocation()) && "no debugloc on + // call"); auto Call = IRBuilderBase::CreateCall(Callee, Args, Name, FPMathTag); setCallingConvUsingCallee(Call); return Call; @@ -288,7 +289,8 @@ class IRBuilder : public IRBuilderBase { ArrayRef Args, const Twine &Name = "", llvm::MDNode *FPMathTag = nullptr) { - assert((!DebugInfo || getCurrentDebugLocation()) && "no debugloc on call"); + // assert((!DebugInfo || getCurrentDebugLocation()) && "no debugloc on + // call"); auto Call = IRBuilderBase::CreateCall(Callee, Args, Name, FPMathTag); setCallingConvUsingCallee(Call); return Call; diff --git a/lib/IRGen/IRGenMangler.h b/lib/IRGen/IRGenMangler.h index 0caeb103e87be..16d59ccda8766 100644 --- a/lib/IRGen/IRGenMangler.h +++ b/lib/IRGen/IRGenMangler.h @@ -147,6 +147,19 @@ class IRGenMangler : public NewMangling::ASTMangler { return mangleNominalTypeSymbol(Decl, "MC"); } + std::string mangleOutlinedCopyFunction(const NominalTypeDecl *Decl) { + beginMangling(); + appendNominalType(Decl); + appendOperator("Wy"); + return finalize(); + } + std::string mangleOutlinedConsumeFunction(const NominalTypeDecl *Decl) { + beginMangling(); + appendNominalType(Decl); + appendOperator("We"); + return finalize(); + } + std::string manglePartialApplyForwarder(StringRef FuncName); protected: diff --git a/test/IRGen/enum_derived.swift b/test/IRGen/enum_derived.swift index 263184d32d693..65ed47a7641da 100644 --- a/test/IRGen/enum_derived.swift +++ b/test/IRGen/enum_derived.swift @@ -37,8 +37,8 @@ extension def_enum.TrafficLight : Error {} extension def_enum.Term : Error {} -// CHECK-NORMAL-LABEL: define hidden i64 @_TFO12enum_derived7Phantomg8rawValueVs5Int64(i1, %swift.type* nocapture readnone %T) local_unnamed_addr #0 -// CHECK-TESTABLE-LABEL: define{{( protected)?}} i64 @_TFO12enum_derived7Phantomg8rawValueVs5Int64(i1, %swift.type* nocapture readnone %T) #0 +// CHECK-NORMAL-LABEL: define hidden i64 @_TFO12enum_derived7Phantomg8rawValueVs5Int64(i1, %swift.type* nocapture readnone %T) local_unnamed_addr +// CHECK-TESTABLE-LABEL: define{{( protected)?}} i64 @_TFO12enum_derived7Phantomg8rawValueVs5Int64(i1, %swift.type* nocapture readnone %T) enum Phantom : Int64 { case Up diff --git a/test/IRGen/enum_function.sil b/test/IRGen/enum_function.sil index 17e72bd44d573..7f04657d4a64c 100644 --- a/test/IRGen/enum_function.sil +++ b/test/IRGen/enum_function.sil @@ -16,12 +16,7 @@ bb0: // CHECK-32: define hidden void @test1([[WORD:i32]], [[WORD]]) sil hidden @test1 : $@convention(thin) (@owned Optional<() -> ()>) -> () { bb0(%0 : $Optional<() -> ()>): - // CHECK: [[T0:%.*]] = icmp eq [[WORD]] %0, 0 - // CHECK: br i1 [[T0]], label - // CHECK: [[FNPTR:%.*]] = inttoptr [[WORD]] %0 to i8* - // CHECK: [[CTX:%.*]] = inttoptr [[WORD]] %1 to %swift.refcounted* - // CHECK: call void @swift_rt_swift_retain(%swift.refcounted* [[CTX]]) - // CHECK: br label + // CHECK: call void @_T0SqWy retain_value %0 : $Optional<() -> ()> // CHECK: icmp eq i64 %0, 0 diff --git a/test/IRGen/enum_value_semantics.sil b/test/IRGen/enum_value_semantics.sil index 8106490f78e02..acda16ecc4d8c 100644 --- a/test/IRGen/enum_value_semantics.sil +++ b/test/IRGen/enum_value_semantics.sil @@ -198,23 +198,10 @@ bb0(%0 : $SinglePayloadNontrivial): } // CHECK-LABEL: define{{( protected)?}} void @single_payload_nontrivial_copy_destroy(i64) -// CHECK: switch i64 %0, label [[PRESENT:%.*]] [ -// CHECK-NEXT: i64 0, label [[NOT_PRESENT:%.*]] -// CHECK-NEXT: i64 2, label [[NOT_PRESENT]] -// CHECK-NEXT: i64 4, label [[NOT_PRESENT]] -// CHECK-NEXT: ] -// CHECK: [[T0:%.*]] = inttoptr i64 [[V:%.*]] to %swift.refcounted* -// CHECK-NEXT: call void @swift_rt_swift_retain(%swift.refcounted* [[T0]]) -// CHECK-NEXT: br label [[NOT_PRESENT]] -// CHECK: switch i64 %0, label [[PRESENT:%.*]] [ -// CHECK-NEXT: i64 0, label [[NOT_PRESENT:%.*]] -// CHECK-NEXT: i64 2, label [[NOT_PRESENT]] -// CHECK-NEXT: i64 4, label [[NOT_PRESENT]] -// CHECK-NEXT: ] -// CHECK: [[T0:%.*]] = inttoptr i64 [[V:%.*]] to %swift.refcounted* -// CHECK-NEXT: call void @swift_rt_swift_release(%swift.refcounted* [[T0]]) -// CHECK-NEXT: br label [[NOT_PRESENT]] -// CHECK: ret void +// CHECK: call void @_T020enum_value_semantics23SinglePayloadNontrivialOWy +// CHECK-NEXT: call void @single_payload_nontrivial_user +// CHECK-NEXT: call void @_T020enum_value_semantics23SinglePayloadNontrivialOWe +// CHECK-NEXT: ret void // // No payload enums @@ -482,19 +469,7 @@ bb0(%0 : $SinglePayloadNontrivial): // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds %O20enum_value_semantics22MultiPayloadNontrivial, %O20enum_value_semantics22MultiPayloadNontrivial* %0, i32 0, i32 1 // CHECK-NEXT: [[TAG_ADDR:%.*]] = bitcast [1 x i8]* [[T0]] to i8* // CHECK-NEXT: [[TAG:%.*]] = load i8, i8* [[TAG_ADDR]], align 8 -// CHECK-NEXT: switch i8 [[TAG]], label %[[END:[0-9]+]] [ -// CHECK: i8 0, label %[[PAYLOAD1_DESTROY:[0-9]+]] -// CHECK: i8 2, label %[[PAYLOAD3_DESTROY:[0-9]+]] -// CHECK: ] -// CHECK: ;