From 66748f71ebc9d1b41cc02414c3dca14939645fbe Mon Sep 17 00:00:00 2001 From: Augusto Noronha Date: Thu, 13 Feb 2025 15:46:07 -0800 Subject: [PATCH] [DebugInfo] Emit debug info for witness tables This change emits debug info for witness tables passed into generic functions when a generic type is constrained to a protocol. This information is required for LLDB's generic expression evaluator to work in such functions. rdar://104446865 --- include/swift/AST/Types.h | 5 +- lib/AST/Type.cpp | 4 +- lib/IRGen/IRGenDebugInfo.cpp | 73 ++++++++++++++----- lib/IRGen/IRGenDebugInfo.h | 6 +- lib/IRGen/IRGenSIL.cpp | 36 ++++++++- lib/IRGen/LocalTypeData.cpp | 59 ++++++++++++--- test/DebugInfo/move_function_dbginfo.swift | 68 ++--------------- test/DebugInfo/witness_table.swift | 73 +++++++++++++++++++ test/IRGen/associated_type_witness.swift | 2 + test/IRGen/associated_types.swift | 4 + test/IRGen/conformance_access_path.swift | 2 +- test/IRGen/fulfillment.sil | 2 +- test/IRGen/generic_structs.sil | 4 +- test/IRGen/generic_structs_future.sil | 4 +- ...result_with_conditional_availability.swift | 4 + test/IRGen/protocol_resilience.sil | 9 ++- 16 files changed, 251 insertions(+), 104 deletions(-) create mode 100644 test/DebugInfo/witness_table.swift diff --git a/include/swift/AST/Types.h b/include/swift/AST/Types.h index 2406fbf5e8b60..057bbda9ac083 100644 --- a/include/swift/AST/Types.h +++ b/include/swift/AST/Types.h @@ -7311,7 +7311,10 @@ class GenericTypeParamType : public SubstitutableType, /// Get the name of the generic type parameter. Identifier getName() const; - + + /// Get the canonical _n_n name; + Identifier getCanonicalName() const; + /// The depth of this generic type parameter, i.e., the number of outer /// levels of generic parameter lists that enclose this type parameter. /// diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 66ce36b9db3a6..2c1d33b5a3897 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -2124,8 +2124,10 @@ Identifier GenericTypeParamType::getName() const { if (!isCanonical()) return Name; - // Otherwise, we're canonical. Produce an anonymous '_n_n' name. + return getCanonicalName(); +} +Identifier GenericTypeParamType::getCanonicalName() const { // getASTContext() doesn't actually mutate an already-canonical type. auto &C = const_cast(this)->getASTContext(); auto &names = C.CanonicalGenericTypeParamTypeNames; diff --git a/lib/IRGen/IRGenDebugInfo.cpp b/lib/IRGen/IRGenDebugInfo.cpp index 7dbfeca194219..2b45c081b630d 100644 --- a/lib/IRGen/IRGenDebugInfo.cpp +++ b/lib/IRGen/IRGenDebugInfo.cpp @@ -279,8 +279,16 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo { DebugTypeInfo DebugType, bool IsLocalToUnit, std::optional Loc); + + void emitArtificialVariable(IRGenFunction &IGF, llvm::Value *Metadata, + StringRef Name, StringRef Identifier); + void emitTypeMetadata(IRGenFunction &IGF, llvm::Value *Metadata, - unsigned Depth, unsigned Index, StringRef Name); + GenericTypeParamType *Type); + + void emitWitnessTable(IRGenFunction &IGF, llvm::Value *Metadata, + StringRef Name, ProtocolDecl *protocol); + void emitPackCountParameter(IRGenFunction &IGF, llvm::Value *Metadata, SILDebugVariable VarInfo); @@ -3904,9 +3912,10 @@ void IRGenDebugInfoImpl::emitGlobalVariableDeclaration( Var->addDebugInfo(GV); } -void IRGenDebugInfoImpl::emitTypeMetadata(IRGenFunction &IGF, - llvm::Value *Metadata, unsigned Depth, - unsigned Index, StringRef Name) { +void IRGenDebugInfoImpl::emitArtificialVariable(IRGenFunction &IGF, + llvm::Value *Metadata, + StringRef Name, + StringRef Identifier) { if (Opts.DebugInfoLevel <= IRGenDebugInfoLevel::LineTables) return; @@ -3915,23 +3924,44 @@ void IRGenDebugInfoImpl::emitTypeMetadata(IRGenFunction &IGF, if (!DS || DS->getInlinedFunction()->isTransparent()) return; - llvm::SmallString<8> Buf; - static const char *Tau = SWIFT_UTF8("\u03C4"); - llvm::raw_svector_ostream OS(Buf); - OS << '$' << Tau << '_' << Depth << '_' << Index; - uint64_t PtrWidthInBits = CI.getTargetInfo().getPointerWidth(clang::LangAS::Default); + uint64_t PtrWidthInBits = + CI.getTargetInfo().getPointerWidth(clang::LangAS::Default); assert(PtrWidthInBits % 8 == 0); auto DbgTy = DebugTypeInfo::getTypeMetadata( getMetadataType(Name)->getDeclaredInterfaceType().getPointer(), Size(PtrWidthInBits / 8), Alignment(CI.getTargetInfo().getPointerAlign(clang::LangAS::Default))); - emitVariableDeclaration(IGF.Builder, Metadata, DbgTy, IGF.getDebugScope(), - {}, {OS.str().str(), 0, false}, - // swift.type is already a pointer type, - // having a shadow copy doesn't add another - // layer of indirection. - IGF.isAsync() ? CoroDirectValue : DirectValue, - ArtificialValue); + emitVariableDeclaration( + IGF.Builder, Metadata, DbgTy, IGF.getDebugScope(), {}, + {Identifier, 0, false}, // swift.type is already a pointer type, + // having a shadow copy doesn't add another + // layer of indirection. + IGF.isAsync() ? CoroDirectValue : DirectValue, ArtificialValue); +} + +void IRGenDebugInfoImpl::emitTypeMetadata(IRGenFunction &IGF, + llvm::Value *Metadata, + GenericTypeParamType *Type) { + llvm::SmallString<8> Buf; + llvm::raw_svector_ostream OS(Buf); + OS << "$" << Type->getCanonicalName().str(); + auto Name = Type->getName().str(); + + emitArtificialVariable(IGF, Metadata, Name, OS.str()); +} + +void IRGenDebugInfoImpl::emitWitnessTable(IRGenFunction &IGF, + llvm::Value *Metadata, StringRef Name, + ProtocolDecl *protocol) { + llvm::SmallString<32> Buf; + llvm::raw_svector_ostream OS(Buf); + DebugTypeInfo DbgTy(protocol->getDeclaredType()); + auto MangledName = getMangledName(DbgTy).Canonical; + OS << "$WT" << Name << "$$" << MangledName;; + // Make sure this ID lives long enough. + auto Id = IGF.getSwiftModule()->getASTContext().getIdentifier(OS.str()); + + emitArtificialVariable(IGF, Metadata, Name, Id.str()); } void IRGenDebugInfoImpl::emitPackCountParameter(IRGenFunction &IGF, @@ -4070,10 +4100,15 @@ void IRGenDebugInfo::emitGlobalVariableDeclaration( } void IRGenDebugInfo::emitTypeMetadata(IRGenFunction &IGF, llvm::Value *Metadata, - unsigned Depth, unsigned Index, - StringRef Name) { + GenericTypeParamType *Type) { static_cast(this)->emitTypeMetadata(IGF, Metadata, - Depth, Index, Name); + Type); +} + +void IRGenDebugInfo::emitWitnessTable(IRGenFunction &IGF, llvm::Value *Metadata, + StringRef Name, ProtocolDecl *protocol) { + static_cast(this)->emitWitnessTable(IGF, Metadata, Name, + protocol); } void IRGenDebugInfo::emitPackCountParameter(IRGenFunction &IGF, diff --git a/lib/IRGen/IRGenDebugInfo.h b/lib/IRGen/IRGenDebugInfo.h index 4007bf3178a25..46e64298bf7db 100644 --- a/lib/IRGen/IRGenDebugInfo.h +++ b/lib/IRGen/IRGenDebugInfo.h @@ -186,7 +186,11 @@ class IRGenDebugInfo { /// Emit debug metadata for type metadata (for generic types). So meta. void emitTypeMetadata(IRGenFunction &IGF, llvm::Value *Metadata, - unsigned Depth, unsigned Index, StringRef Name); + GenericTypeParamType *Type); + + /// Emit debug metadata for a (protocol) witness table. + void emitWitnessTable(IRGenFunction &IGF, llvm::Value *Metadata, + StringRef Name, ProtocolDecl *protocol); /// Emit debug info for the IR function parameter holding the size of one or /// more parameter / type packs. diff --git a/lib/IRGen/IRGenSIL.cpp b/lib/IRGen/IRGenSIL.cpp index fb526f734e755..48d445e6b1437 100644 --- a/lib/IRGen/IRGenSIL.cpp +++ b/lib/IRGen/IRGenSIL.cpp @@ -1168,8 +1168,42 @@ class IRGenSILFunction : emitPackCountDebugVariable(Shape); } }); + + if (auto *BGT = llvm::dyn_cast(Ty)) { + auto Decl = BGT->getDecl(); + auto GE = Decl->getGenericEnvironment(); + auto Requirements = BGT->getDecl() + ->getGenericEnvironment() + ->getGenericSignature() + .getRequirements(); + for (auto Requirement : Requirements) { + if (Requirement.getKind() == RequirementKind::Conformance) { + auto ProtocolDecl = Requirement.getProtocolDecl(); + auto ConformingType = Requirement.getFirstType(); + Type Archetype; + if (auto GTPT = llvm::dyn_cast( + ConformingType.getPointer())) + Archetype = GE->mapTypeIntoContext(GTPT); + else if (auto DMT = llvm::dyn_cast( + ConformingType.getPointer())) + Archetype = GE->mapTypeIntoContext(DMT); + + if (Lowering::TypeConverter::protocolRequiresWitnessTable( + ProtocolDecl) && + tryGetLocalTypeData( + Archetype->getCanonicalType(), + LocalTypeDataKind::forAbstractProtocolWitnessTable( + ProtocolDecl))) { + auto Conformance = + ProtocolConformanceRef::forAbstract(Archetype, ProtocolDecl); + + emitWitnessTableRef(*this, Archetype->getCanonicalType(), + Conformance); + } + } + } + } } - /// Emit debug info for a function argument or a local variable. template void emitDebugVariableDeclaration( diff --git a/lib/IRGen/LocalTypeData.cpp b/lib/IRGen/LocalTypeData.cpp index 048d3ea077126..fca63856e0256 100644 --- a/lib/IRGen/LocalTypeData.cpp +++ b/lib/IRGen/LocalTypeData.cpp @@ -408,26 +408,59 @@ static void maybeEmitDebugInfoForLocalTypeData(IRGenFunction &IGF, // functions that were inlined into transparent functions. Correct would be to // check which instruction requests the type metadata and see whether its // inlined function is transparent. - auto * DS = IGF.getDebugScope(); + auto *DS = IGF.getDebugScope(); if (DS && DS->getInlinedFunction() && DS->getInlinedFunction()->isTransparent()) return; - - // Only for formal type metadata. - if (key.Kind != LocalTypeDataKind::forFormalTypeMetadata()) + // For formal type metadata and witness tables. + ProtocolDecl *proto = nullptr; + + if (key.Kind.isAbstractProtocolConformance()) + proto = key.Kind.getAbstractProtocolConformance(); + else if (key.Kind.isConcreteProtocolConformance()) + proto = key.Kind.getConcreteProtocolConformance()->getProtocol(); + else if (key.Kind != LocalTypeDataKind::forFormalTypeMetadata()) return; // Only for archetypes, and not for opened/opaque archetypes. auto type = dyn_cast(key.Type); if (!type) return; - if (!type->isRoot()) + if (!type->isRoot() && !proto) return; if (!isa(type) && !isa(type)) return; - auto *typeParam = type->getInterfaceType()->castTo(); - auto name = typeParam->getName().str(); + auto interfaceType = type->getInterfaceType(); + llvm::SmallString<16> name; + llvm::SmallString<16> displayName; + if (auto DMT = + llvm::dyn_cast(interfaceType.getPointer())) { + std::function visitDependentMembers = + [&](DependentMemberType *member) { + if (member == nullptr) + return; + if (auto *parent = + llvm::dyn_cast(member->getBase())) { + visitDependentMembers(parent); + name.append("$"); + displayName.append("."); + } + name.append(member->getName().str()); + displayName.append(member->getName().str()); + }; + name.append(DMT->getRootGenericParam()->getCanonicalName().str()); + name.append("$"); + displayName.append(DMT->getRootGenericParam()->getName().str()); + displayName.append("."); + visitDependentMembers(DMT); + } else if (auto GTPT = llvm::dyn_cast( + interfaceType.getPointer())) { + name = GTPT->getCanonicalName().str(); + displayName = GTPT->getName().str(); + } else { + return; + } llvm::Value *data = value.getMetadata(); @@ -438,7 +471,7 @@ static void maybeEmitDebugInfoForLocalTypeData(IRGenFunction &IGF, // though; see the comment in IRGenFunctionSIL::emitShadowCopyIfNeeded(). if (!IGF.IGM.IRGen.Opts.shouldOptimize() && !IGF.isAsync()) { auto alloca = - IGF.createAlloca(data->getType(), IGF.IGM.getPointerAlignment(), name); + IGF.createAlloca(data->getType(), IGF.IGM.getPointerAlignment(), displayName); IGF.Builder.CreateStore(data, alloca); data = alloca.getAddress(); } @@ -447,10 +480,12 @@ static void maybeEmitDebugInfoForLocalTypeData(IRGenFunction &IGF, if (!IGF.IGM.DebugInfo) return; - IGF.IGM.DebugInfo->emitTypeMetadata(IGF, data, - typeParam->getDepth(), - typeParam->getIndex(), - name); + if (proto) { + IGF.IGM.DebugInfo->emitWitnessTable(IGF, data, name, proto); + } else { + auto *typeParam = type->getInterfaceType()->castTo(); + IGF.IGM.DebugInfo->emitTypeMetadata(IGF, data, typeParam); + } } void diff --git a/test/DebugInfo/move_function_dbginfo.swift b/test/DebugInfo/move_function_dbginfo.swift index db2e42e06d487..ecdebac6338e9 100644 --- a/test/DebugInfo/move_function_dbginfo.swift +++ b/test/DebugInfo/move_function_dbginfo.swift @@ -237,6 +237,12 @@ public func copyableVarArgTest(_ k: inout Klass) { // DWARF-NEXT: DW_AT_artificial (true) // // DWARF: DW_TAG_variable +// DWARF: DW_AT_location +// DWARF: DW_AT_name ("$WT\317\204_0_0$$$s3out1P_pD") +// DWARF: DW_AT_type ( +// DWARF: DW_AT_artificial (true) +// +// DWARF: DW_TAG_variable // DWARF-NEXT: DW_AT_location (0x{{[a-z0-9]+}}: // DWARF-NEXT: [0x{{[a-z0-9]+}}, 0x{{[a-z0-9]+}}): // DWARF-NEXT: DW_AT_name ("k") @@ -244,12 +250,6 @@ public func copyableVarArgTest(_ k: inout Klass) { // DWARF-NEXT: DW_AT_decl_line ( // DWARF-NEXT: DW_AT_type ( // -// DWARF: DW_TAG_variable -// DWARF-NEXT: DW_AT_location ( -// DWARF-NEXT: DW_AT_name ("m") -// DWARF-NEXT: DW_AT_decl_file ( -// DWARF-NEXT: DW_AT_decl_line ( -// DWARF-NEXT: DW_AT_type ( public func addressOnlyValueTest(_ x: T) { let k = x k.doSomething() @@ -265,33 +265,6 @@ public func addressOnlyValueTest(_ x: T) { // CHECK: ret void // CHECK-NEXT: } // -// DWARF: DW_AT_linkage_name ("$s3out23addressOnlyValueArgTestyyxnAA1PRzlF") -// DWARF-NEXT: DW_AT_name ("addressOnlyValueArgTest") -// DWARF-NEXT: DW_AT_decl_file ( -// DWARF-NEXT: DW_AT_decl_line ( -// DWARF-NEXT: DW_AT_type ( -// DWARF-NEXT: DW_AT_external ( -// -// DWARF: DW_TAG_formal_parameter -// DWARF-NEXT: DW_AT_location (0x{{[a-z0-9]+}}: -// DWARF-NEXT: [0x{{[a-z0-9]+}}, 0x{{[a-z0-9]+}}): -// DWARF-NEXT: DW_AT_name ("k") -// DWARF-NEXT: DW_AT_decl_file ( -// DWARF-NEXT: DW_AT_decl_line ( -// DWARF-NEXT: DW_AT_type ( -// -// DWARF: DW_TAG_variable -// DWARF-NEXT: DW_AT_location ( -// DWARF-NEXT: DW_AT_name ("$\317\204_0_0") -// DWARF-NEXT: DW_AT_type ( -// DWARF-NEXT: DW_AT_artificial (true) -// -// DWARF: DW_TAG_variable -// DWARF-NEXT: DW_AT_location ( -// DWARF-NEXT: DW_AT_name ("m") -// DWARF-NEXT: DW_AT_decl_file ( -// DWARF-NEXT: DW_AT_decl_line ( -// DWARF-NEXT: DW_AT_type ( public func addressOnlyValueArgTest(_ k: __owned T) { k.doSomething() let m = consume k @@ -306,35 +279,6 @@ public func addressOnlyValueArgTest(_ k: __owned T) { // CHECK: ret void // CHECK-NEXT: } // -// DWARF: DW_AT_linkage_name ("$s3out18addressOnlyVarTestyyxAA1PRzlF") -// DWARF-NEXT: DW_AT_name ("addressOnlyVarTest") -// DWARF-NEXT: DW_AT_decl_file ( -// DWARF-NEXT: DW_AT_decl_line ( -// DWARF-NEXT: DW_AT_type ( -// DWARF-NEXT: DW_AT_external ( -// -// DWARF: DW_TAG_formal_parameter -// DWARF-NEXT: DW_AT_location ( -// DWARF-NEXT: DW_AT_name ("x") -// DWARF-NEXT: DW_AT_decl_file ( -// DWARF-NEXT: DW_AT_decl_line ( -// DWARF-NEXT: DW_AT_type ( -// -// DWARF: DW_TAG_variable -// DWARF-NEXT: DW_AT_location ( -// DWARF-NEXT: DW_AT_name ("$\317\204_0_0") -// DWARF-NEXT: DW_AT_type ( -// DWARF-NEXT: DW_AT_artificial (true) -// -// DWARF: DW_TAG_variable -// DWARF-NEXT: DW_AT_location (0x{{[a-z0-9]+}}: -// DWARF-NEXT: [0x{{[a-z0-9]+}}, 0x{{[a-z0-9]+}}): -// TODO: Missing def in dbg info here. -// DWARF-NEXT: [0x{{[a-z0-9]+}}, 0x{{[a-z0-9]+}}): -// DWARF-NEXT: DW_AT_name ("k") -// DWARF-NEXT: DW_AT_decl_file ( -// DWARF-NEXT: DW_AT_decl_line ( -// DWARF-NEXT: DW_AT_type ( public func addressOnlyVarTest(_ x: T) { var k = x // << this k.doSomething() diff --git a/test/DebugInfo/witness_table.swift b/test/DebugInfo/witness_table.swift new file mode 100644 index 0000000000000..fef40446555b3 --- /dev/null +++ b/test/DebugInfo/witness_table.swift @@ -0,0 +1,73 @@ +// RUN: %target-swift-frontend %s -emit-ir -g -o - +import StdlibUnittest +protocol P1 {} +protocol P2 {} +protocol P3 {} +protocol P4 {} +protocol P5 {} + +struct I: P1, P2, P4 {} +struct I2: P3 {} +struct I3: P5 {} + +struct S where T: P1, T: P2 { + let t: T + let u: U + + func foo() { + } +//CHECK: ![[foo:[0-9]+]] = distinct !DISubprogram(name: "foo", linkageName: "$s13witness_table1SV3fooyyF", +//CHECK: !DILocalVariable(name: "$WT_T_$s13witness_table2P1_pmD", scope: ![[foo]], {{.*}}, flags: DIFlagArtificial) +//CHECK: !DILocalVariable(name: "$WT_T_$s13witness_table2P2_pmD", scope: ![[foo]], {{.*}}, flags: DIFlagArtificial) +//CHECK: !DILocalVariable(name: "$\CF\84_0_0", scope: ![[foo]], {{.*}}, flags: DIFlagArtificial) +//CHECK: !DILocalVariable(name: "$WT_U_$s13witness_table2P3_pmD", scope: ![[foo]], {{.*}}, flags: DIFlagArtificial) +//CHECK: !DILocalVariable(name: "$\CF\84_0_1", scope: ![[foo]], {{.*}}, flags: DIFlagArtificial) + + func bar(v: V) { + } +//CHECK: ![[bar:[0-9]+]] = distinct !DISubprogram(name: "bar", linkageName: "$s13witness_table1SV3bar1vyqd___tAA2P4Rd__lF", +//CHECK: !DILocalVariable(name: "$\CF\84_1_0", scope: ![[bar]], {{.*}}, flags: DIFlagArtificial) +//CHECK: !DILocalVariable(name: "$WT_V_$s13witness_table2P4_pmD", scope: ![[bar]], {{.*}}, flags: DIFlagArtificial) +//CHECK: !DILocalVariable(name: "$WT_T_$s13witness_table2P1_pmD", scope: ![[bar]], {{.*}}, flags: DIFlagArtificial) +//CHECK: !DILocalVariable(name: "$WT_T_$s13witness_table2P2_pmD", scope: ![[bar]], {{.*}}, flags: DIFlagArtificial) +//CHECK: !DILocalVariable(name: "$\CF\84_0_0", scope: ![[bar]], {{.*}}, flags: DIFlagArtificial) +//CHECK: !DILocalVariable(name: "$WT_U_$s13witness_table2P3_pmD", scope: ![[bar]], {{.*}}, flags: DIFlagArtificial) +//CHECK: !DILocalVariable(name: "$\CF\84_0_1", scope: ![[bar]], {{.*}}, flags: DIFlagArtificial) +} + +extension S where T: P5 { + func baz() { + } + +//CHECK: ![[baz:[0-9]+]] = distinct !DISubprogram(name: "baz", linkageName: "$s13witness_table1SVA2A2P5RzrlE3bazyyF", +//CHECK: !DILocalVariable(name: "$WT_T_$s13witness_table2P5_pmD", scope: ![[baz]], {{.*}}, flags: DIFlagArtificial) +//CHECK: !DILocalVariable(name: "$WT_T_$s13witness_table2P1_pmD", scope: ![[baz]], {{.*}}, flags: DIFlagArtificial) +//CHECK: !DILocalVariable(name: "$WT_T_$s13witness_table2P2_pmD", scope: ![[baz]], {{.*}}, flags: DIFlagArtificial) +//CHECK: !DILocalVariable(name: "$\CF\84_0_0", scope: ![[baz]], {{.*}}, flags: DIFlagArtificial) +//CHECK: !DILocalVariable(name: "$WT_U_$s13witness_table2P3_pmD", scope: ![[baz]], {{.*}}, flags: DIFlagArtificial) +//CHECK: !DILocalVariable(name: "$\CF\84_0_1", scope: ![[baz]], {{.*}}, flags: DIFlagArtificial) +} + +S(t: I(), u: I2()) + +func freeFunc(t1: T1, t2: T2) where T2: P3, T2: P4 { +} +//CHECK: ![[freeFunc:[0-9]+]] = distinct !DISubprogram(name: "freeFunc", linkageName: "$s13witness_table8freeFunc2t12t2yx_q_tAA2P1RzAA2P3R_AA2P4R_r0_lF", +//CHECK: !DILocalVariable(name: "$\CF\84_0_0", scope: ![[freeFunc]], {{.*}}, flags: DIFlagArtificial) +//CHECK: !DILocalVariable(name: "$\CF\84_0_1", scope: ![[freeFunc]], {{.*}}, flags: DIFlagArtificial) +//CHECK: !DILocalVariable(name: "$WT_T1_$s13witness_table2P1_pmD", scope: ![[freeFunc]], {{.*}}, flags: DIFlagArtificial) +//CHECK: !DILocalVariable(name: "$WT_T2_$s13witness_table2P3_pmD", scope: ![[freeFunc]], {{.*}}, flags: DIFlagArtificial) +//CHECK: !DILocalVariable(name: "$WT_T2_$s13witness_table2P4_pmD", scope: ![[freeFunc]], {{.*}}, flags: DIFlagArtificial) + +protocol A { + associatedtype Element +} + +func withAssociatedType(_: T) where T.Element: A { +} + +//CHECK: ![[withAssociatedType:[0-9]+]] = distinct !DISubprogram(name: "withAssociatedType", linkageName: "$s13witness_table18withAssociatedTypeyyxAA1ARzAaC7ElementRpzlF" +//CHECK: !DILocalVariable(name: "$\CF\84_0_0", scope: ![[withAssociatedType]], {{.*}}, flags: DIFlagArtificial) +//CHECK: !DILocalVariable(name: "$WT_T_$s13witness_table1A_pmD", scope: ![[withAssociatedType]], {{.*}}, flags: DIFlagArtificial) +//CHECK: !DILocalVariable(name: "$WT_T.Element_$s13witness_table1A_pmD", scope: ![[withAssociatedType]], {{.*}}, flags: DIFlagArtificial) + diff --git a/test/IRGen/associated_type_witness.swift b/test/IRGen/associated_type_witness.swift index 28ace3ab08e99..61be694c438bc 100644 --- a/test/IRGen/associated_type_witness.swift +++ b/test/IRGen/associated_type_witness.swift @@ -73,12 +73,14 @@ struct Fulfilled : Assocked { // CHECK-LABEL: define internal swiftcc ptr @"$s23associated_type_witness9FulfilledVyxGAA8AssockedAA5AssocAaEP_AA1PPWT"(ptr %"Fulfilled.Assoc", ptr %"Fulfilled", ptr %"Fulfilled.Assocked") // CHECK: [[T1:%.*]] = getelementptr inbounds ptr, ptr %"Fulfilled", i64 3 // CHECK-NEXT: [[T2:%.*]] = load ptr, ptr [[T1]], align 8, !invariant.load +// CHECK-NEXT: store ptr %T.P, ptr %T // CHECK-NEXT: ret ptr [[T2]] // Associated type witness table access function for Fulfilled.Assoc : Q. // CHECK-LABEL: define internal swiftcc ptr @"$s23associated_type_witness9FulfilledVyxGAA8AssockedAA5AssocAaEP_AA1QPWT"(ptr %"Fulfilled.Assoc", ptr %"Fulfilled", ptr %"Fulfilled.Assocked") // CHECK: [[T1:%.*]] = getelementptr inbounds ptr, ptr %"Fulfilled", i64 4 // CHECK-NEXT: [[T2:%.*]] = load ptr, ptr [[T1]], align 8, !invariant.load +// CHECK-NEXT: store ptr %T.Q, ptr %T // CHECK-NEXT: ret ptr [[T2]] struct Pair : P, Q {} diff --git a/test/IRGen/associated_types.swift b/test/IRGen/associated_types.swift index 59ae355a87034..e8679364ab5c8 100644 --- a/test/IRGen/associated_types.swift +++ b/test/IRGen/associated_types.swift @@ -81,11 +81,15 @@ func testFastRuncible(_ t: T, u: U) // 2. Get the witness table for U.RuncerType.Runcee : Speedy // 2a. Get the protocol witness table for U.RuncerType : FastRuncer. // CHECK-NEXT: %T.RuncerType.FastRuncer = call swiftcc ptr @swift_getAssociatedConformanceWitness(ptr %U.FastRuncible, ptr %U, ptr [[T3]] +// CHECK-NEXT: store ptr %T.RuncerType.FastRuncer, ptr %T.RuncerType +// CHECK-NEXT: store ptr %T.RuncerType.FastRuncer, ptr %T.RuncerType5 // 1c. Get the type metadata for U.RuncerType.Runcee. // CHECK-NEXT: [[T2:%.*]] = call swiftcc %swift.metadata_response @swift_getAssociatedTypeWitness([[INT]] 0, ptr %T.RuncerType.FastRuncer, ptr [[T3]], {{.*}}, ptr getelementptr inbounds (<{{.*}}>, ptr @"$s16associated_types10FastRuncerMp", i32 0, i32 10)) // CHECK-NEXT: %T.RuncerType.Runcee = extractvalue %swift.metadata_response [[T2]], 0 // 2b. Get the witness table for U.RuncerType.Runcee : Speedy. // CHECK-NEXT: %T.RuncerType.Runcee.Speedy = call swiftcc ptr @swift_getAssociatedConformanceWitness(ptr %T.RuncerType.FastRuncer, ptr [[T3]], ptr %T.RuncerType.Runcee +// CHECK-NEXT: store ptr %T.RuncerType.Runcee.Speedy, ptr %T.RuncerType.Runcee6, align 8 +// CHECK-NEXT: store ptr %T.RuncerType.Runcee.Speedy, ptr %T.RuncerType.Runcee7, align 8 // 3. Perform the actual call. // CHECK-NEXT: [[T0_GEP:%.*]] = getelementptr inbounds ptr, ptr %T.RuncerType.Runcee.Speedy, i32 1 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[T0_GEP]] diff --git a/test/IRGen/conformance_access_path.swift b/test/IRGen/conformance_access_path.swift index 4a03e308721e4..02f51bc0b8572 100644 --- a/test/IRGen/conformance_access_path.swift +++ b/test/IRGen/conformance_access_path.swift @@ -19,7 +19,7 @@ extension Validatable { public func tested(by suite: S.Type) where S.InputType == Self { // CHECK: [[S_AS_VALIDATION_SUITE_GEP:%[0-9]+]] = getelementptr inbounds ptr, ptr %S.ValidationSuite, i32 1 // CHECK: [[S_AS_VALIDATION_SUITE:%.*]] = load ptr, ptr [[S_AS_VALIDATION_SUITE_GEP]] - // CHECK-NEXT: call swiftcc ptr @swift_getAssociatedConformanceWitness(ptr %S.Validator, ptr %S, ptr %Self, + // CHECK: call swiftcc ptr @swift_getAssociatedConformanceWitness(ptr %S.Validator, ptr %S, ptr %Self, tested() } } diff --git a/test/IRGen/fulfillment.sil b/test/IRGen/fulfillment.sil index 89d85a591ef5b..f72f90add1a8c 100644 --- a/test/IRGen/fulfillment.sil +++ b/test/IRGen/fulfillment.sil @@ -32,7 +32,7 @@ sil hidden_external @use_all : $@convention(thin) () - // CHECK: [[METADATA:%.*]] = load ptr, ptr %0, align 8 // CHECK-objc-NEXT: [[T1:%.*]] = getelementptr inbounds ptr, ptr [[METADATA]], i64 10 // CHECK-native-NEXT: [[T1:%.*]] = getelementptr inbounds ptr, ptr [[METADATA]], i64 7 -// CHECK-NEXT: %T = load ptr, ptr [[T1]], align 8 +// CHECK-NEXT: %T1 = load ptr, ptr [[T1]], align 8 // CHECK: store // CHECK-objc-NEXT: [[T1:%.*]] = getelementptr inbounds ptr, ptr [[METADATA]], i64 11 // CHECK-native-NEXT: [[T1:%.*]] = getelementptr inbounds ptr, ptr [[METADATA]], i64 8 diff --git a/test/IRGen/generic_structs.sil b/test/IRGen/generic_structs.sil index 7de16a53c81f8..6c2934020ea12 100644 --- a/test/IRGen/generic_structs.sil +++ b/test/IRGen/generic_structs.sil @@ -231,10 +231,10 @@ struct GenericLayoutWithAssocType { // CHECK: [[T0_GEP:%.*]] = getelementptr inbounds ptr, ptr %T.ParentHasAssociatedType, i32 1 // CHECK: [[T0:%.*]] = load ptr, ptr [[T0_GEP]] -// CHECK: [[T4:%.*]] = call swiftcc %swift.metadata_response @swift_getAssociatedTypeWitness(i64 0, ptr %T.HasAssociatedType, ptr %T, ptr @"$s15generic_structs17HasAssociatedTypeTL", ptr @"$s5Assoc15generic_structs17HasAssociatedTypePTl") +// CHECK: [[T4:%.*]] = call swiftcc %swift.metadata_response @swift_getAssociatedTypeWitness(i64 0, ptr %T.HasAssociatedType, ptr %T3, ptr @"$s15generic_structs17HasAssociatedTypeTL", ptr @"$s5Assoc15generic_structs17HasAssociatedTypePTl") // CHECK: %T.Assoc = extractvalue %swift.metadata_response [[T4]], 0 -// CHECK: %T.Assoc.HasAssociatedType = call swiftcc ptr @swift_getAssociatedConformanceWitness(ptr %T.ParentHasAssociatedType, ptr %T, ptr %T.Assoc, +// CHECK: %T.Assoc.HasAssociatedType = call swiftcc ptr @swift_getAssociatedConformanceWitness(ptr %T.ParentHasAssociatedType, ptr %T3, ptr %T.Assoc, // CHECK: [[T2:%.*]] = call swiftcc %swift.metadata_response @swift_getAssociatedTypeWitness(i64 0, ptr %T.Assoc.HasAssociatedType, ptr %T.Assoc, ptr @"$s15generic_structs17HasAssociatedTypeTL", ptr @"$s5Assoc15generic_structs17HasAssociatedTypePTl") // CHECK: %T.Assoc.Assoc = extractvalue %swift.metadata_response [[T2]], 0 diff --git a/test/IRGen/generic_structs_future.sil b/test/IRGen/generic_structs_future.sil index 84b3fa9aa6a00..c2c3924d77cb7 100644 --- a/test/IRGen/generic_structs_future.sil +++ b/test/IRGen/generic_structs_future.sil @@ -232,10 +232,10 @@ struct GenericLayoutWithAssocType { // CHECK: [[T0_GEP:%.*]] = getelementptr inbounds ptr, ptr %T.ParentHasAssociatedType, i32 1 // CHECK: [[T0:%.*]] = load ptr, ptr [[T0_GEP]] -// CHECK: [[T4:%.*]] = call swiftcc %swift.metadata_response @swift_getAssociatedTypeWitness(i64 0, ptr %T.HasAssociatedType, ptr %T, ptr @"$s22generic_structs_future17HasAssociatedTypeTL", ptr @"$s5Assoc22generic_structs_future17HasAssociatedTypePTl") +// CHECK: [[T4:%.*]] = call swiftcc %swift.metadata_response @swift_getAssociatedTypeWitness(i64 0, ptr %T.HasAssociatedType, ptr %T3, ptr @"$s22generic_structs_future17HasAssociatedTypeTL", ptr @"$s5Assoc22generic_structs_future17HasAssociatedTypePTl") // CHECK: %T.Assoc = extractvalue %swift.metadata_response [[T4]], 0 -// CHECK: %T.Assoc.HasAssociatedType = call swiftcc ptr @swift_getAssociatedConformanceWitness(ptr %T.ParentHasAssociatedType, ptr %T, ptr %T.Assoc, +// CHECK: %T.Assoc.HasAssociatedType = call swiftcc ptr @swift_getAssociatedConformanceWitness(ptr %T.ParentHasAssociatedType, ptr %T3, ptr %T.Assoc, // CHECK: [[T2:%.*]] = call swiftcc %swift.metadata_response @swift_getAssociatedTypeWitness(i64 0, ptr %T.Assoc.HasAssociatedType, ptr %T.Assoc, ptr @"$s22generic_structs_future17HasAssociatedTypeTL", ptr @"$s5Assoc22generic_structs_future17HasAssociatedTypePTl") // CHECK: %T.Assoc.Assoc = extractvalue %swift.metadata_response [[T2]], 0 diff --git a/test/IRGen/opaque_result_with_conditional_availability.swift b/test/IRGen/opaque_result_with_conditional_availability.swift index 4825974981b0f..f410404922709 100644 --- a/test/IRGen/opaque_result_with_conditional_availability.swift +++ b/test/IRGen/opaque_result_with_conditional_availability.swift @@ -181,10 +181,12 @@ func test_multiple_generic(_ t: T) -> some P { // CHECK: define private ptr @"get_underlying_type_ref 43opaque_result_with_conditional_availabilityAA21test_multiple_genericyQrxAA1PRzlFQOQr"(ptr %0) // CHECK-NEXT: entry: // CHECK-NEXT: %"\CF\84_0_01" = alloca ptr +// CHECK-NEXT: %"\CF\84_0_02" = alloca ptr // CHECK-NEXT: %"\CF\84_0_0" = load ptr, ptr %0 // CHECK-NEXT: store ptr %"\CF\84_0_0", ptr %"\CF\84_0_01" // CHECK-NEXT: %1 = getelementptr inbounds ptr, ptr %0, i32 1 // CHECK-NEXT: %"\CF\84_0_0.P" = load ptr, ptr %1 +// CHECK-NEXT: store ptr %"\CF\84_0_0.P", ptr %"\CF\84_0_02" // CHECK-NEXT: br label %conditional-0 // CHECK: conditional-0: ; preds = %entry // CHECK-NEXT: br label %cond-0-0 @@ -201,10 +203,12 @@ func test_multiple_generic(_ t: T) -> some P { // CHECK: define private ptr @"get_underlying_witness 43opaque_result_with_conditional_availabilityAA21test_multiple_genericyQrxAA1PRzlFQOqd__AaCHC"(ptr %0) // CHECK-NEXT: entry: // CHECK-NEXT: %"\CF\84_0_01" = alloca ptr, align 8 +// CHECK-NEXT: %"\CF\84_0_02" = alloca ptr, align 8 // CHECK-NEXT: %"\CF\84_0_0" = load ptr, ptr %0, align 8 // CHECK-NEXT: store ptr %"\CF\84_0_0", ptr %"\CF\84_0_01", align 8 // CHECK-NEXT: %1 = getelementptr inbounds ptr, ptr %0, i32 1 // CHECK-NEXT: %"\CF\84_0_0.P" = load ptr, ptr %1, align 8 +// CHECK-NEXT: store ptr %"\CF\84_0_0.P", ptr %"\CF\84_0_02" // CHECK-NEXT: br label %conditional-0 // CHECK: conditional-0: ; preds = %entry // CHECK-NEXT: br label %cond-0-0 diff --git a/test/IRGen/protocol_resilience.sil b/test/IRGen/protocol_resilience.sil index 7d2c1784e7401..148f7e3bd1e7c 100644 --- a/test/IRGen/protocol_resilience.sil +++ b/test/IRGen/protocol_resilience.sil @@ -1,7 +1,6 @@ // RUN: %empty-directory(%t) // RUN: %target-swift-frontend -emit-module -enable-library-evolution -emit-module-path=%t/resilient_protocol.swiftmodule -module-name=resilient_protocol %S/../Inputs/resilient_protocol.swift // RUN: %target-swift-frontend -I %t -emit-ir -Xllvm -sil-disable-pass=Simplification -enable-library-evolution %s | %FileCheck %s -DINT=i%target-ptrsize -// RUN: %target-swift-frontend -I %t -emit-ir -Xllvm -sil-disable-pass=Simplification -enable-library-evolution -O %s sil_stage canonical @@ -141,7 +140,9 @@ protocol InternalProtocol { sil @defaultC : $@convention(witness_method: ResilientProtocol) (@in_guaranteed Self) -> () { bb0(%0 : $*Self): // CHECK-NEXT: %[[SELF:.*]] = alloca ptr + // CHECK-NEXT:%[[SELF2:.*]] = alloca ptr // CHECK-NEXT: store ptr %Self, ptr %[[SELF]] + // CHECK-NEXT: store ptr %SelfWitnessTable, ptr %[[SELF2]] // CHECK-NEXT: ret void %result = tuple () return %result : $() @@ -155,7 +156,9 @@ bb0(%0 : $*Self): // Make sure we can emit direct references to other default implementations // CHECK-NEXT: %[[SELF:.*]] = alloca ptr + // CHECK-NEXT:%[[SELF2:.*]] = alloca ptr // CHECK-NEXT: store ptr %Self, ptr %[[SELF]] + // CHECK-NEXT: store ptr %SelfWitnessTable, ptr %[[SELF2]] // CHECK-NEXT: call swiftcc void @defaultC(ptr noalias swiftself %0, ptr %Self, ptr %SelfWitnessTable) %fn1 = function_ref @defaultC : $@convention(witness_method: ResilientProtocol) (@in_guaranteed Self) -> () %ignore1 = apply %fn1(%0) : $@convention(witness_method: ResilientProtocol) (@in_guaranteed Self) -> () @@ -193,7 +196,9 @@ bb0(%0 : $@thick Self.Type): // Make sure we can emit direct references to other default implementations // CHECK-NEXT: %[[SELF:.*]] = alloca ptr + // CHECK-NEXT:%[[SELF2:.*]] = alloca ptr // CHECK-NEXT: store ptr %Self, ptr %[[SELF]] + // CHECK-NEXT: store ptr %SelfWitnessTable, ptr %[[SELF2]] // CHECK-NEXT: call swiftcc void @defaultF(ptr swiftself %0, ptr %Self, ptr %SelfWitnessTable) %fn1 = function_ref @defaultF : $@convention(witness_method: ResilientProtocol) (@thick Self.Type) -> () %ignore1 = apply %fn1(%0) : $@convention(witness_method: ResilientProtocol) (@thick Self.Type) -> () @@ -229,7 +234,9 @@ bb0(%0 : $@thick Self.Type): sil @defaultF : $@convention(witness_method: ResilientProtocol) (@thick Self.Type) -> () { bb0(%0 : $@thick Self.Type): // CHECK-NEXT: %[[SELF:.*]] = alloca ptr + // CHECK-NEXT:%[[SELF2:.*]] = alloca ptr // CHECK-NEXT: store ptr %Self, ptr %[[SELF]] + // CHECK-NEXT: store ptr %SelfWitnessTable, ptr %[[SELF2]] // CHECK-NEXT: ret void %result = tuple () return %result : $()