diff --git a/include/swift/IRGen/GenericRequirement.h b/include/swift/IRGen/GenericRequirement.h index a917715918044..720b60b0d514e 100644 --- a/include/swift/IRGen/GenericRequirement.h +++ b/include/swift/IRGen/GenericRequirement.h @@ -58,16 +58,6 @@ class GenericRequirement { GenericRequirement(Kind kind, CanType type, ProtocolDecl *proto) : kind(kind), type(type), proto(proto) {} - static bool isPack(CanType ty) { - if (auto gp = dyn_cast(ty)) - return gp->isParameterPack(); - if (auto dm = dyn_cast(ty)) - if (auto gp = - dyn_cast(dm->getBase()->getCanonicalType())) - return gp->isParameterPack(); - return false; - } - public: Kind getKind() const { return kind; @@ -91,7 +81,7 @@ class GenericRequirement { } bool isMetadata() const { - return kind == Kind::Metadata; + return kind == Kind::Metadata || kind == Kind::MetadataPack; } static GenericRequirement forMetadata(CanType type, bool isPack) { @@ -100,11 +90,11 @@ class GenericRequirement { } static GenericRequirement forMetadata(CanType type) { - return forMetadata(type, isPack(type)); + return forMetadata(type, type->hasParameterPack()); } bool isWitnessTable() const { - return kind == Kind::WitnessTable; + return kind == Kind::WitnessTable || kind == Kind::WitnessTablePack; } static GenericRequirement forWitnessTable(CanType type, ProtocolDecl *proto, @@ -114,7 +104,7 @@ class GenericRequirement { } static GenericRequirement forWitnessTable(CanType type, ProtocolDecl *proto) { - return forWitnessTable(type, proto, isPack(type)); + return forWitnessTable(type, proto, type->hasParameterPack()); } static llvm::Type *typeForKind(irgen::IRGenModule &IGM, diff --git a/lib/IRGen/GenPack.cpp b/lib/IRGen/GenPack.cpp index b17348ae06186..d39ef774436a2 100644 --- a/lib/IRGen/GenPack.cpp +++ b/lib/IRGen/GenPack.cpp @@ -21,6 +21,7 @@ #include "swift/AST/IRGenOptions.h" #include "swift/AST/PackConformance.h" #include "swift/AST/Types.h" +#include "swift/IRGen/GenericRequirement.h" #include "swift/SIL/SILModule.h" #include "swift/SIL/SILType.h" #include "llvm/IR/DerivedTypes.h" @@ -205,64 +206,153 @@ static Address emitFixedSizeMetadataPackRef(IRGenFunction &IGF, return pack; } -static llvm::Value *emitPackExpansionElementMetadata( - IRGenFunction &IGF, CanPackExpansionType expansionTy, llvm::Value *index, - DynamicMetadataRequest request) { - auto patternTy = expansionTy.getPatternType(); +static llvm::Value *bindMetadataAtIndex(IRGenFunction &IGF, + CanType elementArchetype, + llvm::Value *patternPack, + llvm::Value *index, + DynamicMetadataRequest request) { + if (auto response = IGF.tryGetLocalTypeMetadata(elementArchetype, request)) + return response.getMetadata(); - // Find all the pack archetypes appearing in the pattern type. - SmallVector patternPacks; - patternTy->getTypeParameterPacks(patternPacks); + patternPack = + IGF.Builder.CreatePointerCast(patternPack, IGF.IGM.TypeMetadataPtrPtrTy); - // Get the outer generic signature and environment. - auto *genericEnv = cast(expansionTy.getCountType()) - ->getGenericEnvironment(); - auto subMap = genericEnv->getForwardingSubstitutionMap(); + Address patternPackAddress(patternPack, IGF.IGM.TypeMetadataPtrTy, + IGF.IGM.getPointerAlignment()); - auto genericSig = genericEnv->getGenericSignature().getCanonicalSignature(); + // Load the metadata pack element from the current source index. + Address fromPtr( + IGF.Builder.CreateInBoundsGEP(patternPackAddress.getElementType(), + patternPackAddress.getAddress(), index), + patternPackAddress.getElementType(), patternPackAddress.getAlignment()); + llvm::Value *metadata = IGF.Builder.CreateLoad(fromPtr); - // Create an opened element signature and environment. - auto elementSig = IGF.IGM.Context.getOpenedElementSignature( - genericSig, expansionTy.getCountType()); - auto *elementEnv = GenericEnvironment::forOpenedElement( - elementSig, UUID::fromTime(), expansionTy.getCountType(), subMap); + // Bind the metadata pack element to the element archetype. + IGF.setScopedLocalTypeMetadata(elementArchetype, + MetadataResponse::forComplete(metadata)); - // Open each pack archetype. - for (auto patternPackType : patternPacks) { - // Get the metadata for the pack archetype. - auto patternPackArchetype = cast( - patternPackType->getCanonicalType()); - auto patternPack = IGF.emitTypeMetadataRef(patternPackArchetype, request) - .getMetadata(); + return metadata; +} - patternPack = IGF.Builder.CreatePointerCast( - patternPack, IGF.IGM.TypeMetadataPtrPtrTy); +static llvm::Value *bindWitnessTableAtIndex(IRGenFunction &IGF, + CanType elementArchetype, + ProtocolConformanceRef conf, + llvm::Value *wtablePack, + llvm::Value *index) { + auto key = LocalTypeDataKind::forProtocolWitnessTable(conf); + if (auto *wtable = IGF.tryGetLocalTypeData(elementArchetype, key)) + return wtable; + wtablePack = + IGF.Builder.CreatePointerCast(wtablePack, IGF.IGM.WitnessTablePtrPtrTy); - Address patternPackAddress(patternPack, IGF.IGM.TypeMetadataPtrTy, - IGF.IGM.getPointerAlignment()); + Address patternPackAddress(wtablePack, IGF.IGM.WitnessTablePtrTy, + IGF.IGM.getPointerAlignment()); - // Load the metadata pack element from the current source index. - Address fromPtr( + // Load the witness table pack element from the current source index. + Address fromPtr( IGF.Builder.CreateInBoundsGEP(patternPackAddress.getElementType(), - patternPackAddress.getAddress(), - index), - patternPackAddress.getElementType(), - patternPackAddress.getAlignment()); - auto metadata = IGF.Builder.CreateLoad(fromPtr); - - // Bind the metadata pack element to the element archetype. - auto elementArchetype = - elementEnv->mapPackTypeIntoElementContext( - patternPackArchetype->getInterfaceType()); - - IGF.setScopedLocalTypeMetadata( - CanType(elementArchetype), - MetadataResponse::forComplete(metadata)); + patternPackAddress.getAddress(), index), + patternPackAddress.getElementType(), patternPackAddress.getAlignment()); + auto *wtable = IGF.Builder.CreateLoad(fromPtr); + + // Bind the witness table pack element to the element archetype. + IGF.setScopedLocalTypeData(elementArchetype, key, wtable); + + return wtable; +} + +struct OpenedElementContext { + GenericEnvironment *packEnvironment; + CanGenericSignature packSignature; + + GenericEnvironment *elementEnvironment; + CanGenericSignature elementSignature; + + static OpenedElementContext + createForPackExpansion(IRGenFunction &IGF, CanPackExpansionType expansionTy) { + // Get the outer generic signature and environment. + auto *genericEnv = cast(expansionTy.getCountType()) + ->getGenericEnvironment(); + auto subMap = genericEnv->getForwardingSubstitutionMap(); + + auto genericSig = genericEnv->getGenericSignature().getCanonicalSignature(); + // Create an opened element signature and environment. + auto elementSig = IGF.IGM.Context.getOpenedElementSignature( + genericSig, expansionTy.getCountType()); + auto *elementEnv = GenericEnvironment::forOpenedElement( + elementSig, UUID::fromTime(), expansionTy.getCountType(), subMap); + + return {genericEnv, genericSig, elementEnv, elementSig}; } +}; + +static void bindElementSignatureRequirementsAtIndex( + IRGenFunction &IGF, OpenedElementContext const &context, llvm::Value *index, + DynamicMetadataRequest request) { + enumerateGenericSignatureRequirements( + context.elementSignature, [&](GenericRequirement requirement) { + switch (requirement.getKind()) { + case GenericRequirement::Kind::Shape: + case GenericRequirement::Kind::Metadata: + case GenericRequirement::Kind::WitnessTable: + break; + case GenericRequirement::Kind::MetadataPack: { + auto ty = requirement.getTypeParameter(); + auto patternPackArchetype = cast( + context.packEnvironment->mapTypeIntoContext(ty) + ->getCanonicalType()); + auto response = + IGF.emitTypeMetadataRef(patternPackArchetype, request); + auto elementArchetype = + context.elementEnvironment + ->mapPackTypeIntoElementContext( + patternPackArchetype->getInterfaceType()) + ->getCanonicalType(); + auto *patternPack = response.getMetadata(); + auto elementMetadata = bindMetadataAtIndex( + IGF, elementArchetype, patternPack, index, request); + assert(elementMetadata); + (void)elementMetadata; + break; + } + case GenericRequirement::Kind::WitnessTablePack: { + auto ty = requirement.getTypeParameter(); + auto proto = requirement.getProtocol(); + auto patternPackArchetype = cast( + context.packEnvironment->mapTypeIntoContext(ty) + ->getCanonicalType()); + auto elementArchetype = + context.elementEnvironment + ->mapPackTypeIntoElementContext( + patternPackArchetype->getInterfaceType()) + ->getCanonicalType(); + llvm::Value *_metadata = nullptr; + auto packConformance = + context.packSignature->lookupConformance(ty, proto); + auto *wtablePack = emitWitnessTableRef(IGF, patternPackArchetype, + &_metadata, packConformance); + auto elementConformance = + context.elementSignature->lookupConformance(ty, proto); + auto *wtable = bindWitnessTableAtIndex( + IGF, elementArchetype, elementConformance, wtablePack, index); + assert(wtable); + (void)wtable; + break; + } + } + }); +} + +static llvm::Value *emitPackExpansionElementMetadata( + IRGenFunction &IGF, OpenedElementContext context, CanType patternTy, + llvm::Value *index, DynamicMetadataRequest request) { + bindElementSignatureRequirementsAtIndex(IGF, context, index, request); // Replace pack archetypes with element archetypes in the pattern type. - auto instantiatedPatternTy = elementEnv->mapPackTypeIntoElementContext( - patternTy->mapTypeOutOfContext())->getCanonicalType(); + auto instantiatedPatternTy = + context.elementEnvironment + ->mapPackTypeIntoElementContext(patternTy->mapTypeOutOfContext()) + ->getCanonicalType(); // Emit the element metadata. auto element = IGF.emitTypeMetadataRef(instantiatedPatternTy, request) @@ -270,11 +360,14 @@ static llvm::Value *emitPackExpansionElementMetadata( return element; } -static void emitPackExpansionType(IRGenFunction &IGF, Address pack, - CanPackExpansionType expansionTy, - llvm::Value *dynamicIndex, - llvm::Value *dynamicLength, - DynamicMetadataRequest request) { +/// Store the values corresponding to the specified pack expansion \p +/// expansionTy for each index in its range [dynamicIndex, dynamicIndex + +/// dynamicLength) produced by the provided function \p elementForIndex into +/// the indicated buffer \p pack. +static void emitPackExpansionPack( + IRGenFunction &IGF, Address pack, CanPackExpansionType expansionTy, + llvm::Value *dynamicIndex, llvm::Value *dynamicLength, + function_ref elementForIndex) { auto *prev = IGF.Builder.GetInsertBlock(); auto *check = IGF.createBasicBlock("pack-expansion-check"); auto *loop = IGF.createBasicBlock("pack-expansion-loop"); @@ -293,8 +386,7 @@ static void emitPackExpansionType(IRGenFunction &IGF, Address pack, IGF.Builder.emitBlock(loop); - auto *element = - emitPackExpansionElementMetadata(IGF, expansionTy, phi, request); + auto *element = elementForIndex(phi); // Store the element metadata into to the current destination index. auto *eltIndex = IGF.Builder.CreateAdd(dynamicIndex, phi); @@ -320,6 +412,21 @@ static void emitPackExpansionType(IRGenFunction &IGF, Address pack, IGF.Builder.emitBlock(rest); } +static void emitPackExpansionMetadataPack(IRGenFunction &IGF, Address pack, + CanPackExpansionType expansionTy, + llvm::Value *dynamicIndex, + llvm::Value *dynamicLength, + DynamicMetadataRequest request) { + emitPackExpansionPack( + IGF, pack, expansionTy, dynamicIndex, dynamicLength, [&](auto *index) { + auto context = + OpenedElementContext::createForPackExpansion(IGF, expansionTy); + auto patternTy = expansionTy.getPatternType(); + return emitPackExpansionElementMetadata(IGF, context, patternTy, index, + request); + }); +} + StackAddress irgen::emitTypeMetadataPack(IRGenFunction &IGF, CanPackType packType, @@ -346,8 +453,8 @@ irgen::emitTypeMetadataPack(IRGenFunction &IGF, } if (auto expansionTy = dyn_cast(eltTy)) { - emitPackExpansionType(IGF, pack.getAddress(), expansionTy, - dynamicIndex, dynamicLength, request); + emitPackExpansionMetadataPack(IGF, pack.getAddress(), expansionTy, + dynamicIndex, dynamicLength, request); } else { Address eltPtr( IGF.Builder.CreateInBoundsGEP(pack.getAddress().getElementType(), @@ -399,9 +506,10 @@ static Address emitFixedSizeWitnessTablePack(IRGenFunction &IGF, IGF.Builder.CreateStructGEP(pack, i, IGF.IGM.getPointerSize()); auto conformance = packConformance->getPatternConformances()[i]; + llvm::Value *_metadata = nullptr; auto *wtable = emitWitnessTableRef(IGF, packType.getElementType(i), - /*srcMetadataCache=*/nullptr, conformance); + /*srcMetadataCache=*/&_metadata, conformance); IGF.Builder.CreateStore(wtable, slot); } @@ -410,118 +518,41 @@ static Address emitFixedSizeWitnessTablePack(IRGenFunction &IGF, } static llvm::Value *emitPackExpansionElementWitnessTable( - IRGenFunction &IGF, CanPackExpansionType expansionTy, - ProtocolConformanceRef conformance, llvm::Value *index) { - auto patternTy = expansionTy.getPatternType(); - - // Find all the pack archetypes appearing in the pattern type. - SmallVector patternPacks; - patternTy->getTypeParameterPacks(patternPacks); - - // Get the outer generic signature and environment. - auto *genericEnv = cast(expansionTy.getCountType()) - ->getGenericEnvironment(); - auto subMap = genericEnv->getForwardingSubstitutionMap(); - - auto genericSig = genericEnv->getGenericSignature().getCanonicalSignature(); - - // Create an opened element signature and environment. - auto elementSig = IGF.IGM.Context.getOpenedElementSignature( - genericSig, expansionTy.getCountType()); - auto *elementEnv = GenericEnvironment::forOpenedElement( - elementSig, UUID::fromTime(), expansionTy.getCountType(), subMap); - - // Open each pack archetype. - for (auto patternPackType : patternPacks) { - // Get the witness table for the pack archetype. - auto patternPackArchetype = - cast(patternPackType->getCanonicalType()); - for (auto *proto : patternPackArchetype->getConformsTo()) { - auto conf = ProtocolConformanceRef(proto); - auto patternPack = emitWitnessTableRef( - IGF, patternPackArchetype, /*srcMetadataCache=*/nullptr, conf); - - patternPack = IGF.Builder.CreatePointerCast(patternPack, - IGF.IGM.WitnessTablePtrPtrTy); - - Address patternPackAddress(patternPack, IGF.IGM.WitnessTablePtrTy, - IGF.IGM.getPointerAlignment()); - - // Load the witness table pack element from the current source index. - Address fromPtr( - IGF.Builder.CreateInBoundsGEP(patternPackAddress.getElementType(), - patternPackAddress.getAddress(), index), - patternPackAddress.getElementType(), - patternPackAddress.getAlignment()); - auto *wtable = IGF.Builder.CreateLoad(fromPtr); - - // Bind the witness table pack element to the element archetype. - auto elementArchetype = elementEnv->mapPackTypeIntoElementContext( - patternPackArchetype->getInterfaceType()); - - IGF.setScopedLocalTypeData( - CanType(elementArchetype), - LocalTypeDataKind::forProtocolWitnessTable(conf), wtable); - } - } + IRGenFunction &IGF, OpenedElementContext context, CanType patternTy, + ProtocolConformanceRef conformance, llvm::Value **srcMetadataCache, + llvm::Value *index) { + bindElementSignatureRequirementsAtIndex(IGF, context, index, + MetadataState::Complete); // Replace pack archetypes with element archetypes in the pattern type. auto instantiatedPatternTy = - elementEnv + context.elementEnvironment ->mapPackTypeIntoElementContext(patternTy->mapTypeOutOfContext()) ->getCanonicalType(); + auto instantiatedConformance = + context.elementEnvironment->getGenericSignature()->lookupConformance( + instantiatedPatternTy, conformance.getRequirement()); // Emit the element witness table. auto *wtable = emitWitnessTableRef(IGF, instantiatedPatternTy, - /*srcMetadataCache=*/nullptr, conformance); + srcMetadataCache, instantiatedConformance); return wtable; } -static void emitExpansionWitnessTablePack(IRGenFunction &IGF, Address pack, - CanPackExpansionType expansionTy, - ProtocolConformanceRef conformance, - llvm::Value *dynamicIndex, - llvm::Value *dynamicLength) { - auto *prev = IGF.Builder.GetInsertBlock(); - auto *check = IGF.createBasicBlock("pack-expansion-check"); - auto *loop = IGF.createBasicBlock("pack-expansion-loop"); - auto *rest = IGF.createBasicBlock("pack-expansion-rest"); - - IGF.Builder.CreateBr(check); - IGF.Builder.emitBlock(check); - - // An index into the source witness table pack. - auto *phi = IGF.Builder.CreatePHI(IGF.IGM.SizeTy, 2); - phi->addIncoming(llvm::ConstantInt::get(IGF.IGM.SizeTy, 0), prev); - - // If we reach the end, jump to the continuation block. - auto *cond = IGF.Builder.CreateICmpULT(phi, dynamicLength); - IGF.Builder.CreateCondBr(cond, loop, rest); - - IGF.Builder.emitBlock(loop); - - auto *element = - emitPackExpansionElementWitnessTable(IGF, expansionTy, conformance, phi); - - // Store the element witness table into to the current destination index. - auto *eltIndex = IGF.Builder.CreateAdd(dynamicIndex, phi); - Address eltPtr(IGF.Builder.CreateInBoundsGEP(pack.getElementType(), - pack.getAddress(), eltIndex), - pack.getElementType(), pack.getAlignment()); - - IGF.Builder.CreateStore(element, eltPtr); - - // Increment our counter. - auto *next = - IGF.Builder.CreateAdd(phi, llvm::ConstantInt::get(IGF.IGM.SizeTy, 1)); - - phi->addIncoming(next, loop); - - // Repeat the loop. - IGF.Builder.CreateBr(check); - - // Fall through. - IGF.Builder.emitBlock(rest); +static void emitPackExpansionWitnessTablePack( + IRGenFunction &IGF, Address pack, CanPackExpansionType expansionTy, + ProtocolConformanceRef conformance, llvm::Value *dynamicIndex, + llvm::Value *dynamicLength) { + emitPackExpansionPack( + IGF, pack, expansionTy, dynamicIndex, dynamicLength, [&](auto *index) { + llvm::Value *_metadata = nullptr; + auto context = + OpenedElementContext::createForPackExpansion(IGF, expansionTy); + auto patternTy = expansionTy.getPatternType(); + return emitPackExpansionElementWitnessTable( + IGF, context, patternTy, conformance, + /*srcMetadataCache=*/&_metadata, index); + }); } StackAddress irgen::emitWitnessTablePack(IRGenFunction &IGF, @@ -550,16 +581,18 @@ StackAddress irgen::emitWitnessTablePack(IRGenFunction &IGF, auto conformance = packConformance->getPatternConformances()[index]; if (auto expansionTy = dyn_cast(eltTy)) { - emitExpansionWitnessTablePack(IGF, pack.getAddress(), expansionTy, - conformance, dynamicIndex, dynamicLength); + emitPackExpansionWitnessTablePack(IGF, pack.getAddress(), expansionTy, + conformance, dynamicIndex, + dynamicLength); } else { Address eltPtr( IGF.Builder.CreateInBoundsGEP(pack.getAddress().getElementType(), pack.getAddressPointer(), dynamicIndex), pack.getAddress().getElementType(), pack.getAlignment()); + llvm::Value *_metadata = nullptr; auto *wtable = emitWitnessTableRef( - IGF, eltTy, /*srcMetadataCache=*/nullptr, conformance); + IGF, eltTy, /*srcMetadataCache=*/&_metadata, conformance); IGF.Builder.CreateStore(wtable, eltPtr); } ++index; @@ -659,8 +692,10 @@ llvm::Value *irgen::emitTypeMetadataPackElementRef( auto response = IGF.emitTypeMetadataRef(ty, request); auto *metadata = response.getMetadata(); for (auto protocol : protocols) { - auto *wtable = emitWitnessTableRef(IGF, ty, /*srcMetadataCache=*/nullptr, - ProtocolConformanceRef(protocol)); + llvm::Value *_metadata = nullptr; + auto *wtable = + emitWitnessTableRef(IGF, ty, /*srcMetadataCache=*/&_metadata, + ProtocolConformanceRef(protocol)); wtables.push_back(wtable); } return metadata; @@ -830,18 +865,23 @@ llvm::Value *irgen::emitTypeMetadataPackElementRef( // Actually materialize %inner. Then use it to get the metadata from the // pack expansion at that index. auto *relativeIndex = IGF.Builder.CreateSub(index, lowerBound); - metadata = emitPackExpansionElementMetadata(IGF, expansionTy, + auto context = + OpenedElementContext::createForPackExpansion(IGF, expansionTy); + auto patternTy = expansionTy.getPatternType(); + metadata = emitPackExpansionElementMetadata(IGF, context, patternTy, relativeIndex, request); for (auto protocol : protocols) { auto *wtable = emitPackExpansionElementWitnessTable( - IGF, expansionTy, ProtocolConformanceRef(protocol), relativeIndex); + IGF, context, patternTy, ProtocolConformanceRef(protocol), + &metadata, relativeIndex); wtables.push_back(wtable); } } else { metadata = IGF.emitTypeMetadataRef(elementTy, request).getMetadata(); for (auto protocol : protocols) { + llvm::Value *_metadata = nullptr; auto *wtable = - emitWitnessTableRef(IGF, elementTy, /*srcMetadataCache=*/nullptr, + emitWitnessTableRef(IGF, elementTy, /*srcMetadataCache=*/&_metadata, ProtocolConformanceRef(protocol)); wtables.push_back(wtable); } diff --git a/test/IRGen/run_variadic_generics.sil b/test/IRGen/run_variadic_generics.sil index 35605df96d552..57ce877fe01e6 100644 --- a/test/IRGen/run_variadic_generics.sil +++ b/test/IRGen/run_variadic_generics.sil @@ -1,5 +1,5 @@ // RUN: %empty-directory(%t) -// RUN: %target-build-swift-dylib(%t/%target-library-name(PrintShims)) %S/../Inputs/print-shims.swift -module-name PrintShims -emit-module -emit-module-path %t/PrintShims.swiftmodule +// RUN: %target-build-swift-dylib(%t/%target-library-name(PrintShims)) -parse-stdlib %S/../Inputs/print-shims-stdlib.swift -module-name PrintShims -emit-module -emit-module-path %t/PrintShims.swiftmodule // RUN: %target-codesign %t/%target-library-name(PrintShims) // RUN: %target-build-swift -enable-experimental-feature VariadicGenerics -g -parse-sil %s -emit-ir -I %t -L %t -lPrintShim | %FileCheck %s --check-prefix=CHECK-LL // RUN: %target-build-swift -enable-experimental-feature VariadicGenerics -g -parse-sil %s -module-name main -o %t/main -I %t -L %t -lPrintShims %target-rpath(%t) @@ -18,6 +18,7 @@ import Swift import PrintShims sil public_external @printGenericType : $@convention(thin) (@thick T.Type) -> () +sil public_external @printGenericTypeAndWord : $@convention(thin) (@thick T.Type, Builtin.Word) -> () protocol P { static func static_member_fn() @@ -45,10 +46,15 @@ struct G : P { static func static_member_fn() } +struct GenFwdP : P { + static func static_member_fn() +} + sil private @A_static_member_fn : $@convention(witness_method: P) (@thick A.Type) -> () { bb0(%0 : $@thick A.Type): - %printGenericType = function_ref @printGenericType : $@convention(thin) (@thick T.Type) -> () - apply %printGenericType(%0) : $@convention(thin) (@thick T.Type) -> () + %printGenericTypeAndWord = function_ref @printGenericTypeAndWord : $@convention(thin) (@thick T.Type, Builtin.Word) -> () + %id = integer_literal $Builtin.Word, 0 + apply %printGenericTypeAndWord(%0, %id) : $@convention(thin) (@thick T.Type, Builtin.Word) -> () %4 = tuple () return %4 : $() } @@ -57,8 +63,9 @@ sil_witness_table A : P module main { } sil private @B_static_member_fn : $@convention(witness_method: P) (@thick B.Type) -> () { bb0(%0 : $@thick B.Type): - %printGenericType = function_ref @printGenericType : $@convention(thin) (@thick T.Type) -> () - apply %printGenericType(%0) : $@convention(thin) (@thick T.Type) -> () + %printGenericTypeAndWord = function_ref @printGenericTypeAndWord : $@convention(thin) (@thick T.Type, Builtin.Word) -> () + %id = integer_literal $Builtin.Word, 1 + apply %printGenericTypeAndWord(%0, %id) : $@convention(thin) (@thick T.Type, Builtin.Word) -> () %4 = tuple () return %4 : $() } @@ -67,8 +74,9 @@ sil_witness_table B : P module main { } sil private @C_static_member_fn : $@convention(witness_method: P) (@thick C.Type) -> () { bb0(%0 : $@thick C.Type): - %printGenericType = function_ref @printGenericType : $@convention(thin) (@thick T.Type) -> () - apply %printGenericType(%0) : $@convention(thin) (@thick T.Type) -> () + %printGenericTypeAndWord = function_ref @printGenericTypeAndWord : $@convention(thin) (@thick T.Type, Builtin.Word) -> () + %id = integer_literal $Builtin.Word, 2 + apply %printGenericTypeAndWord(%0, %id) : $@convention(thin) (@thick T.Type, Builtin.Word) -> () %4 = tuple () return %4 : $() } @@ -77,8 +85,9 @@ sil_witness_table C : P module main { } sil private @D_static_member_fn : $@convention(witness_method: P) (@thick D.Type) -> () { bb0(%0 : $@thick D.Type): - %printGenericType = function_ref @printGenericType : $@convention(thin) (@thick T.Type) -> () - apply %printGenericType(%0) : $@convention(thin) (@thick T.Type) -> () + %printGenericTypeAndWord = function_ref @printGenericTypeAndWord : $@convention(thin) (@thick T.Type, Builtin.Word) -> () + %id = integer_literal $Builtin.Word, 3 + apply %printGenericTypeAndWord(%0, %id) : $@convention(thin) (@thick T.Type, Builtin.Word) -> () %4 = tuple () return %4 : $() } @@ -87,8 +96,9 @@ sil_witness_table D : P module main { } sil private @E_static_member_fn : $@convention(witness_method: P) (@thick E.Type) -> () { bb0(%0 : $@thick E.Type): - %printGenericType = function_ref @printGenericType : $@convention(thin) (@thick T.Type) -> () - apply %printGenericType(%0) : $@convention(thin) (@thick T.Type) -> () + %printGenericTypeAndWord = function_ref @printGenericTypeAndWord : $@convention(thin) (@thick T.Type, Builtin.Word) -> () + %id = integer_literal $Builtin.Word, 4 + apply %printGenericTypeAndWord(%0, %id) : $@convention(thin) (@thick T.Type, Builtin.Word) -> () %4 = tuple () return %4 : $() } @@ -97,8 +107,9 @@ sil_witness_table E : P module main { } sil private @F_static_member_fn : $@convention(witness_method: P) (@thick F.Type) -> () { bb0(%0 : $@thick F.Type): - %printGenericType = function_ref @printGenericType : $@convention(thin) (@thick T.Type) -> () - apply %printGenericType(%0) : $@convention(thin) (@thick T.Type) -> () + %printGenericTypeAndWord = function_ref @printGenericTypeAndWord : $@convention(thin) (@thick T.Type, Builtin.Word) -> () + %id = integer_literal $Builtin.Word, 5 + apply %printGenericTypeAndWord(%0, %id) : $@convention(thin) (@thick T.Type, Builtin.Word) -> () %4 = tuple () return %4 : $() } @@ -107,8 +118,9 @@ sil_witness_table F : P module main { } sil private @G_static_member_fn : $@convention(witness_method: P) (@thick G.Type) -> () { bb0(%0 : $@thick G.Type): - %printGenericType = function_ref @printGenericType : $@convention(thin) (@thick T.Type) -> () - apply %printGenericType(%0) : $@convention(thin) (@thick T.Type) -> () + %printGenericTypeAndWord = function_ref @printGenericTypeAndWord : $@convention(thin) (@thick T.Type, Builtin.Word) -> () + %id = integer_literal $Builtin.Word, 6 + apply %printGenericTypeAndWord(%0, %id) : $@convention(thin) (@thick T.Type, Builtin.Word) -> () %4 = tuple () return %4 : $() } @@ -116,6 +128,21 @@ sil_witness_table G : P module main { method #P.static_member_fn: (Self.Type) -> () -> () : @G_static_member_fn } +sil private @GenFwdP_static_member_fn : $@convention(witness_method: P) (@thick GenFwdP.Type) -> () { +bb0(%0 : $@thick GenFwdP.Type): + %printGenericType = function_ref @printGenericType : $@convention(thin) (@thick T.Type) -> () + apply %printGenericType>(%0) : $@convention(thin) (@thick T.Type) -> () + %forwardee = metatype $@thick T.Type + %forwarded_static_member_fn = witness_method $T, #P.static_member_fn : (Self.Type) -> () -> () : $@convention(witness_method: P) (@thick T.Type) -> () + apply %forwarded_static_member_fn(%forwardee) : $@convention(witness_method: P) (@thick T.Type) -> () + %4 = tuple () + return %4 : $() +} + +sil_witness_table GenFwdP: P module main { + method #P.static_member_fn: (Self.Type) -> () -> () : @GenFwdP_static_member_fn +} + sil [ossa] @main : $@convention(c) (Int32, UnsafeMutablePointer>>) -> Int32 { bb0(%argc : $Int32, %argv : $UnsafeMutablePointer>>): %0 = integer_literal $Builtin.Word, 0 @@ -205,55 +232,67 @@ bb0(%argc : $Int32, %argv : $UnsafeMutablePointer ^ // CHECK: A // CHECK: A + // CHECK: 0 // U_2 -> {D, E, F, A, B, C} // ---0--> ^ // CHECK: D // CHECK: D + // CHECK: 3 apply %two_archetypes_from_two_params_no_singles_with_conformance(%0) : $@convention(thin) (Builtin.Word) -> () // U_1 -> {A, B, C, D, E, F} // ----1----> ^ // CHECK: B // CHECK: B + // CHECK: 1 // U_2 -> {D, E, F, A, B, C} // ----1----> ^ // CHECK: E // CHECK: E + // CHECK: 4 apply %two_archetypes_from_two_params_no_singles_with_conformance(%1) : $@convention(thin) (Builtin.Word) -> () // U_1 -> {A, B, C, D, E, F} // ------2-----> ^ // CHECK: C // CHECK: C + // CHECK: 2 // U_2 -> {D, E, F, A, B, C} // ------2-----> ^ // CHECK: F // CHECK: F + // CHECK: 5 apply %two_archetypes_from_two_params_no_singles_with_conformance(%2) : $@convention(thin) (Builtin.Word) -> () // U_1 -> {A, B, C, D, E, F} // -------3-------> ^ // CHECK: D // CHECK: D + // CHECK: 3 // U_2 -> {D, E, F, A, B, C} // -------3-------> ^ // CHECK: A // CHECK: A + // CHECK: 0 apply %two_archetypes_from_two_params_no_singles_with_conformance(%3) : $@convention(thin) (Builtin.Word) -> () // U_1 -> {A, B, C, D, E, F} // ---------4--------> ^ // CHECK: E // CHECK: E + // CHECK: 4 // U_2 -> {D, E, F, A, B, C} // ---------4--------> ^ // CHECK: B // CHECK: B + // CHECK: 1 apply %two_archetypes_from_two_params_no_singles_with_conformance(%4) : $@convention(thin) (Builtin.Word) -> () // U_1 -> {A, B, C, D, E, F} // -----------5---------> ^ // CHECK: F // CHECK: F + // CHECK: 5 // U_2 -> {D, E, F, A, B, C} // -----------5---------> ^ // CHECK: C // CHECK: C + // CHECK: 2 apply %two_archetypes_from_two_params_no_singles_with_conformance(%5) : $@convention(thin) (Builtin.Word) -> () @@ -262,33 +301,90 @@ bb0(%argc : $Int32, %argv : $UnsafeMutablePointer ^ // CHECK: A // CHECK: A + // CHECK: 0 apply %direct_access_from_parameter_with_conformance(%0) : $@convention(thin) (Builtin.Word) -> () // U_1 -> {A, B, C, D, E, F} // ----1----> ^ // CHECK: B // CHECK: B + // CHECK: 1 apply %direct_access_from_parameter_with_conformance(%1) : $@convention(thin) (Builtin.Word) -> () // U_1 -> {A, B, C, D, E, F} // -----2------> ^ // CHECK: C // CHECK: C + // CHECK: 2 apply %direct_access_from_parameter_with_conformance(%2) : $@convention(thin) (Builtin.Word) -> () // U_1 -> {A, B, C, D, E, F} // -------3-------> ^ // CHECK: D // CHECK: D + // CHECK: 3 apply %direct_access_from_parameter_with_conformance(%3) : $@convention(thin) (Builtin.Word) -> () // U_1 -> {A, B, C, D, E, F} // --------4---------> ^ // CHECK: E // CHECK: E + // CHECK: 4 apply %direct_access_from_parameter_with_conformance(%4) : $@convention(thin) (Builtin.Word) -> () // U_1 -> {A, B, C, D, E, F} // ----------5----------> ^ // CHECK: F // CHECK: F + // CHECK: 5 apply %direct_access_from_parameter_with_conformance(%5) : $@convention(thin) (Builtin.Word) -> () + + /// Expect the following + /// GenFwdP // from direct_access_from_parameter_with_conformance's call to printGenericType + /// GenFwdP // from GenFwdP_static_member_fn's call to printGenericType + /// INNER // from INNER::static_member_fn's call to printGenericTypeAndWord + /// INNER.INDEX // from INNER::static_member_fn's call to printGenericTypeAndWord + %wrap_in_GenFwdP = function_ref @wrap_in_GenFwdP : $@convention(thin) (Builtin.Word) -> () + // U_1 -> {A, B, C, D, E, F} + // --0---> ^ + // CHECK: GenFwdP + // CHECK: GenFwdP + // CHECK: A + // CHECK: 0 + apply %wrap_in_GenFwdP(%0) : $@convention(thin) (Builtin.Word) -> () + // U_1 -> {A, B, C, D, E, F} + // ----1----> ^ + // CHECK: GenFwdP + // CHECK: GenFwdP + // CHECK: B + // CHECK: 1 + apply %wrap_in_GenFwdP(%1) : $@convention(thin) (Builtin.Word) -> () + // U_1 -> {A, B, C, D, E, F} + // -----2------> ^ + // CHECK: GenFwdP + // CHECK: GenFwdP + // CHECK: C + // CHECK: 2 + apply %wrap_in_GenFwdP(%2) : $@convention(thin) (Builtin.Word) -> () + // U_1 -> {A, B, C, D, E, F} + // -------3-------> ^ + // CHECK: GenFwdP + // CHECK: GenFwdP + // CHECK: D + // CHECK: 3 + apply %wrap_in_GenFwdP(%3) : $@convention(thin) (Builtin.Word) -> () + // U_1 -> {A, B, C, D, E, F} + // --------4---------> ^ + // CHECK: GenFwdP + // CHECK: GenFwdP + // CHECK: E + // CHECK: 4 + apply %wrap_in_GenFwdP(%4) : $@convention(thin) (Builtin.Word) -> () + // U_1 -> {A, B, C, D, E, F} + // ----------5----------> ^ + // CHECK: GenFwdP + // CHECK: GenFwdP + // CHECK: F + // CHECK: 5 + apply %wrap_in_GenFwdP(%5) : $@convention(thin) (Builtin.Word) -> () + + %outb = integer_literal $Builtin.Int32, 0 %out = struct $Int32 (%outb : $Builtin.Int32) return %out : $Int32 @@ -367,3 +463,11 @@ entry(%intIndex : $Builtin.Word): %t = tuple () return %t : $() } + +sil @wrap_in_GenFwdP : $ (Builtin.Word) -> () { +entry(%intIndex : $Builtin.Word): + %direct_access_from_parameter_with_conformance = function_ref @direct_access_from_parameter_with_conformance : $@convention(thin) (Builtin.Word) -> () + apply %direct_access_from_parameter_with_conformance}>(%intIndex) : $@convention(thin) (Builtin.Word) -> () + %t = tuple () + return %t : $() +} diff --git a/test/IRGen/variadic_generic_functions.sil b/test/IRGen/variadic_generic_functions.sil index d8189f5ec3c9f..f4dd58b1eae45 100644 --- a/test/IRGen/variadic_generic_functions.sil +++ b/test/IRGen/variadic_generic_functions.sil @@ -1,4 +1,4 @@ -// RUN: %target-swift-frontend -parse-sil -emit-ir -primary-file %s -enable-experimental-feature VariadicGenerics | %FileCheck %s +// RUN: %target-swift-frontend -parse-sil -emit-ir -primary-file %s -enable-experimental-feature VariadicGenerics | %IRGenFileCheck %s // Because of -enable-experimental-feature VariadicGenerics // REQUIRES: asserts @@ -7,6 +7,15 @@ import Builtin import Swift protocol P {} +protocol PA { + associatedtype A +} +protocol Q {} +protocol QA { + associatedtype A +} +protocol R {} + struct S : P {} sil_witness_table S : P module main {} struct S_2 : P {} @@ -14,6 +23,11 @@ sil_witness_table S_2 : P module main {} struct S_3 : P {} sil_witness_table S_3 : P module main {} +struct Gen1 : PA where Fwd.A : Q { + typealias A = Fwd.A +} +struct Gen2 : Q {} + // CHECK-LABEL: define {{.*}}void @c() // CHECK: entry: // CHECK: [[METADATA_PACK:%[^,]+]] = alloca [1 x %swift.type*] @@ -24,7 +38,7 @@ sil_witness_table S_3 : P module main {} // CHECK: store i8** getelementptr inbounds {{.*}}$s26variadic_generic_functions3S_2VAA1PAAWP{{.*}}, i8*** [[WTABLE_ELEMENT_0]] // CHECK: [[METADATA_PACK_PTR:%[^,]+]] = bitcast [1 x %swift.type*]* [[METADATA_PACK]] to %swift.type** // CHECK: [[WTABLE_PACK_ADDR:%[^,]+]] = bitcast [1 x i8**]* [[WTABLE_PACK]] to i8*** -// CHECK: call swiftcc void @g(i{{(64|32)}} 1, %swift.type** [[METADATA_PACK_PTR]], i8*** [[WTABLE_PACK_ADDR]]) +// CHECK: call swiftcc void @g([[INT]] 1, %swift.type** [[METADATA_PACK_PTR]], i8*** [[WTABLE_PACK_ADDR]]) sil @c : $() -> () { %g = function_ref @g : $@convention(thin) () -> () apply %g() : $@convention(thin) () -> () @@ -32,7 +46,7 @@ sil @c : $() -> () { return %ret : $() } -// CHECK: define {{.*}}void @g(i{{(64|32)}} %0, %swift.type** %T, i8*** %T.P) +// CHECK: define {{.*}}void @g([[INT]] %0, %swift.type** %T, i8*** %T.P) sil @g : $ () -> () { %f = function_ref @f : $@convention(thin) () -> () apply %f() : $@convention(thin) () -> () @@ -40,9 +54,13 @@ sil @g : $ () -> () { return %ret : $() } +// Forward polymorphic parameters: 1 size, 1 metadata pack, 1 wtable pack // Verify that polymorphic parameters are just forwarded along. -// CHECK-LABEL: define {{.*}}void @f(i{{(32|64)}} %0, %swift.type** %T, i8*** %T.P) -// CHECK: call swiftcc void @fc(i{{(32|64)}} %0, %swift.type** %T, i8*** %T.P) +// CHECK-LABEL: define {{.*}}void @f( +// CHECK-SAME: [[INT]] %0, +// CHECK-SAME: %swift.type** %T, +// CHECK-SAME: i8*** %T.P) +// CHECK: call swiftcc void @fc([[INT]] %0, %swift.type** %T, i8*** %T.P) sil @f : $ () -> () { %fc = function_ref @fc : $@convention(thin) () -> () apply %fc() : $@convention(thin) () -> () @@ -51,12 +69,13 @@ sil @f : $ () -> () { } sil @fc : $ () -> () {} -protocol PA { - associatedtype A -} - -// CHECK-LABEL: define {{.*}}@f1(i{{(32|64)}} %0, %swift.type** %T, i8*** %T.PA, i8*** %T.A.P) -// CHECK: call swiftcc void @f1c(i{{(32|64)}} %0, %swift.type** %T, i8*** %T.PA, i8*** %T.A.P) +// Forward polymorphic parameters: 1 size, 1 metadata pack, 2 wtable packs +// CHECK-LABEL: define {{.*}}@f1( +// CHECK-SAME: [[INT]] %0, +// CHECK-SAME: %swift.type** %T, +// CHECK-SAME: i8*** %T.PA, +// CHECK-SAME: i8*** %T.A.P) +// CHECK: call swiftcc void @f1c([[INT]] %0, %swift.type** %T, i8*** %T.PA, i8*** %T.A.P) sil @f1 : $ () -> () { %f1c = function_ref @f1c : $@convention(thin) () -> () apply %f1c() : $@convention(thin) () -> () @@ -65,3 +84,106 @@ sil @f1 : $ () -> () { } sil @f1c : $ () -> () {} + +// Construct associatedtype metadata pack, forward root wtable pack. +// CHECK-LABEL: define {{.*}}@associatedtype_with_added_conformance( +// CHECK-SAME: [[INT]] [[SHAPE:%[^,]+]], +// CHECK-SAME: %swift.type** %T, +// CHECK-SAME: i8*** %T.PA, +// CHECK-SAME: i8*** [[ASSOCIATEDTYPES_CONFORMANCES_TO_Q:%[^,]+]]) +// CHECK: [[ASSOCIATEDTYPES:%[^,]+]] = alloca %swift.type*, [[INT]] [[SHAPE]] +// CHECK: call swiftcc void @associatedtype_with_added_conformance_callee( +// CHECK-SAME: [[INT]] [[SHAPE]], +// CHECK-SAME: %swift.type** [[ASSOCIATEDTYPES]], +// CHECK-SAME: i8*** [[ASSOCIATEDTYPES_CONFORMANCES_TO_Q]]) +sil @associatedtype_with_added_conformance : $ () -> () { + %callee = function_ref @associatedtype_with_added_conformance_callee : $@convention(thin) () -> () + apply %callee() : $@convention(thin) () -> () + %ret = tuple () + return %ret : $() +} +sil @associatedtype_with_added_conformance_callee : $ () -> () {} + +// Construct nested associatedtype pack, forward root wtable pack. +// CHECK-LABEL: define {{.*}}@associatedtype_with_added_conformance_2( +// CHECK-SAME: [[INT]] [[SHAPE:%[^,]+]], +// CHECK-SAME: %swift.type** %T, +// CHECK-SAME: i8*** %T.PA, +// CHECK-SAME: i8*** %T.A.QA, +// CHECK-SAME: i8*** [[ASSOCIATEDTYPES_CONFORMANCES_TO_Q:%[^,]+]]) +// CHECK: [[ASSOCIATEDTYPES:%[^,]+]] = alloca %swift.type*, [[INT]] [[SHAPE]] +// CHECK: call swiftcc void @associatedtype_with_added_conformance_2_callee( +// CHECK-SAME: [[INT]] [[SHAPE]], +// CHECK-SAME: %swift.type** [[ASSOCIATEDTYPES]], +// CHECK-SAME: i8*** [[ASSOCIATEDTYPES_CONFORMANCES_TO_Q]]) +sil @associatedtype_with_added_conformance_2 : $ () -> () { + %j = function_ref @associatedtype_with_added_conformance_2_callee : $@convention(thin) () -> () + apply %j() : $@convention(thin) () -> () + %ret = tuple () + return %ret : $() +} +sil @associatedtype_with_added_conformance_2_callee : $ () -> () {} + +// Construct a pack of generic types which "forward" conformance to a protocol. +// CHECK-LABEL: define {{.*}}@associatedtype_with_forwarded_conformance_1( +// CHECK-SAME: [[INT]] [[SHAPE:%[^,]+]], +// CHECK-SAME: %swift.type** %T, +// CHECK-SAME: i8*** %T.Q) +// CHECK: [[GEN2_TYPES:%[^,]+]] = alloca %swift.type*, [[INT]] [[SHAPE]] +// CHECK: [[GEN2_CONFORMANCES_TO_Q:%[^,]+]] = alloca i8**, [[INT]] [[SHAPE]] +// CHECK: call swiftcc void @associatedtype_with_forwarded_conformance_1_callee( +// CHECK-SAME: [[INT]] [[SHAPE]], +// CHECK-SAME: %swift.type** [[GEN2_TYPES]], +// CHECK-SAME: i8*** [[GEN2_CONFORMANCES_TO_Q]]) +sil @associatedtype_with_forwarded_conformance_1 : $ () -> () { + %i = function_ref @associatedtype_with_forwarded_conformance_1_callee : $@convention(thin) () -> () + apply %i}>() : $@convention(thin) () -> () + %ret = tuple () + return %ret : $() +} +sil @associatedtype_with_forwarded_conformance_1_callee : $ () -> () { +} + +// Construct a pack of generic types which "forward" conformance to a protocol with an associatedtype which itself conforms to a protocol. +// CHECK-LABEL: define {{.*}}@generictype_with_forwarded_conformance_2( +// CHECK-SAME: [[INT]] [[SHAPE:%[^,]+]], +// CHECK-SAME: %swift.type** %T, +// CHECK-SAME: i8*** %T.PA, +// CHECK-SAME: i8*** %T.A.Q) +// CHECK: [[GEN1_TYPES:%[^,]+]] = alloca %swift.type*, [[INT]] [[SHAPE]] +// CHECK: [[GEN1_CONFORMANCES_TO_PA:%[^,]+]] = alloca i8**, [[INT]] [[SHAPE]] +// CHECK: call swiftcc void @generictype_with_forwarded_conformance_2_callee( +// CHECK-SAME: [[INT]] [[SHAPE]], +// CHECK-SAME: %swift.type** [[GEN1_TYPES]], +// CHECK-SAME: i8*** [[GEN1_CONFORMANCES_TO_PA]], +// CHECK-SAME: i8*** %T.A.Q) +sil @generictype_with_forwarded_conformance_2 : $() -> () { + %callee = function_ref @generictype_with_forwarded_conformance_2_callee : $@convention(thin) () -> () + apply %callee}>() : $@convention(thin) () -> () + %ret = tuple () + return %ret : $() +} +sil @generictype_with_forwarded_conformance_2_callee : $ () -> () {} + +// Construct a pack of generic types of generic types which "forward" conformance to a protocol with an associatedtype which itself conforms to a protocol. +// CHECK-LABEL: define {{.*}}@generic_with_forwarded_conformance_3( +// CHECK-SAME: [[INT]] [[SHAPE:%[^,]+]], +// CHECK-SAME: %swift.type** %T, +// CHECK-SAME: i8*** %T.PA, +// CHECK-SAME: i8*** %T.A.Q) +// CHECK: [[GEN1_GEN1_TYPES:%[^,]+]] = alloca %swift.type*, [[INT]] [[SHAPE]] +// CHECK: [[GEN1_GEN1_CONFORMANCES_TO_PA:%[^,]+]] = alloca i8**, [[INT]] [[SHAPE]] +// CHECK: call swiftcc void @generic_with_forwarded_conformance_3_callee( +// CHECK-SAME: [[INT]] [[SHAPE]], +// CHECK-SAME: %swift.type** [[GEN1_GEN1_TYPES]], +// CHECK-SAME: i8*** [[GEN1_GEN1_CONFORMANCES_TO_PA]], +// CHECK-SAME: i8*** %T.A.Q) +sil @generic_with_forwarded_conformance_3 : $ () -> () { + %callee = function_ref @generic_with_forwarded_conformance_3_callee : $@convention(thin) () -> () + apply %callee>}>() : $@convention(thin) () -> () + %ret = tuple () + return %ret : $() +} +sil @generic_with_forwarded_conformance_3_callee : $ () -> () { +} + diff --git a/test/Inputs/print-shims-stdlib.swift b/test/Inputs/print-shims-stdlib.swift new file mode 100644 index 0000000000000..6414452634275 --- /dev/null +++ b/test/Inputs/print-shims-stdlib.swift @@ -0,0 +1,12 @@ +import Swift + +@_silgen_name("printGenericType") +public func printGenericType(_ t: T.Type) { + print(T.self) +} + +@_silgen_name("printGenericTypeAndWord") +public func printGenericType(_ t: T.Type, _ w: Builtin.Word) { + print(T.self, Int(w)) +} +