Skip to content

Commit d8f1917

Browse files
authored
Merge pull request #20640 from DougGregor/keypath-type-accessors
2 parents 85a2cc4 + d4fe6e9 commit d8f1917

File tree

17 files changed

+392
-105
lines changed

17 files changed

+392
-105
lines changed

docs/ABI/Mangling.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,9 @@ The following symbolic reference kinds are currently implemented:
9090
dependent-associated-conformance ::= '\x05' .{4} // Reference points directly to associated conformance descriptor (NOT IMPLEMENTED)
9191
dependent-associated-conformance ::= '\x06' .{4} // Reference points indirectly to associated conformance descriptor (NOT IMPLEMENTED)
9292

93-
associated-conformance-acceess-function ::= '\x07' .{4} // Reference points directly to associated conformance access function relative to the protocol
94-
associated-conformance-acceess-function ::= '\x08' .{4} // Reference points directly to associated conformance access function relative to the conforming type
95-
keypath-metadata-access-function ::= '\x09' {.4} // Reference points directly to keypath type metadata access function
93+
associated-conformance-access-function ::= '\x07' .{4} // Reference points directly to associated conformance access function relative to the protocol
94+
associated-conformance-access-function ::= '\x08' .{4} // Reference points directly to associated conformance access function relative to the conforming type
95+
keypath-metadata-access-function ::= '\x09' {.4} // Reference points directly to keypath conformance access function
9696

9797
Globals
9898
~~~~~~~

include/swift/ABI/Metadata.h

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2611,6 +2611,57 @@ class TargetGenericRequirementDescriptor {
26112611
using GenericRequirementDescriptor =
26122612
TargetGenericRequirementDescriptor<InProcess>;
26132613

2614+
template<typename Runtime>
2615+
class TargetGenericEnvironment
2616+
: public swift::ABI::TrailingObjects<TargetGenericEnvironment<Runtime>,
2617+
uint16_t, GenericParamDescriptor,
2618+
TargetGenericRequirementDescriptor<Runtime>> {
2619+
using GenericRequirementDescriptor =
2620+
TargetGenericRequirementDescriptor<Runtime>;
2621+
using TrailingObjects =
2622+
swift::ABI::TrailingObjects<TargetGenericEnvironment<Runtime>,
2623+
uint16_t, GenericParamDescriptor, GenericRequirementDescriptor>;
2624+
friend TrailingObjects;
2625+
2626+
template<typename T>
2627+
using OverloadToken = typename TrailingObjects::template OverloadToken<T>;
2628+
2629+
size_t numTrailingObjects(OverloadToken<uint16_t>) const {
2630+
return Flags.getNumGenericParameterLevels();
2631+
}
2632+
2633+
size_t numTrailingObjects(OverloadToken<GenericParamDescriptor>) const {
2634+
return getGenericParameterCounts().back();
2635+
}
2636+
2637+
size_t numTrailingObjects(OverloadToken<GenericRequirementDescriptor>) const {
2638+
return Flags.getNumGenericRequirements();
2639+
}
2640+
2641+
GenericEnvironmentFlags Flags;
2642+
2643+
public:
2644+
/// Retrieve the cumulative generic parameter counts at each level of genericity.
2645+
ArrayRef<uint16_t> getGenericParameterCounts() const {
2646+
return ArrayRef<uint16_t>(this->template getTrailingObjects<uint16_t>(),
2647+
Flags.getNumGenericParameterLevels());
2648+
}
2649+
2650+
/// Retrieve the generic parameters descriptors.
2651+
ArrayRef<GenericParamDescriptor> getGenericParameters() const {
2652+
return ArrayRef<GenericParamDescriptor>(
2653+
this->template getTrailingObjects<GenericParamDescriptor>(),
2654+
getGenericParameterCounts().back());
2655+
}
2656+
2657+
/// Retrieve the generic requirements.
2658+
ArrayRef<GenericRequirementDescriptor> getGenericRequirements() const {
2659+
return ArrayRef<GenericRequirementDescriptor>(
2660+
this->template getTrailingObjects<GenericRequirementDescriptor>(),
2661+
Flags.getNumGenericRequirements());
2662+
}
2663+
};
2664+
26142665
/// CRTP class for a context descriptor that includes trailing generic
26152666
/// context description.
26162667
template<class Self,

include/swift/ABI/MetadataValues.h

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1508,6 +1508,45 @@ enum class GenericRequirementLayoutKind : uint32_t {
15081508
Class = 0,
15091509
};
15101510

1511+
class GenericEnvironmentFlags {
1512+
uint32_t Value;
1513+
1514+
enum : uint32_t {
1515+
NumGenericParameterLevelsMask = 0xFFF,
1516+
NumGenericRequirementsShift = 12,
1517+
NumGenericRequirementsMask = 0xFFFF << NumGenericRequirementsShift,
1518+
};
1519+
1520+
constexpr explicit GenericEnvironmentFlags(uint32_t value) : Value(value) { }
1521+
1522+
public:
1523+
constexpr GenericEnvironmentFlags() : Value(0) { }
1524+
1525+
constexpr GenericEnvironmentFlags
1526+
withNumGenericParameterLevels(uint16_t numGenericParameterLevels) const {
1527+
return GenericEnvironmentFlags((Value &~ NumGenericParameterLevelsMask)
1528+
| numGenericParameterLevels);
1529+
}
1530+
1531+
constexpr GenericEnvironmentFlags
1532+
withNumGenericRequirements(uint16_t numGenericRequirements) const {
1533+
return GenericEnvironmentFlags((Value &~ NumGenericRequirementsMask)
1534+
| (numGenericRequirements << NumGenericRequirementsShift));
1535+
}
1536+
1537+
constexpr unsigned getNumGenericParameterLevels() const {
1538+
return Value & NumGenericParameterLevelsMask;
1539+
}
1540+
1541+
constexpr unsigned getNumGenericRequirements() const {
1542+
return (Value & NumGenericRequirementsMask) >> NumGenericRequirementsShift;
1543+
}
1544+
1545+
constexpr uint32_t getIntValue() const {
1546+
return Value;
1547+
}
1548+
};
1549+
15111550
/// Flags used by generic metadata patterns.
15121551
class GenericMetadataPatternFlags : public FlagSet<uint32_t> {
15131552
enum {

lib/Demangling/Demangler.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ swift::Demangle::makeSymbolicMangledNameStringRef(const char *base) {
136136
// Skip over symbolic references.
137137
if (*end >= '\x01' && *end <= '\x17')
138138
end += sizeof(uint32_t);
139-
if (*end >= '\x18' && *end <= '\x1F')
139+
else if (*end >= '\x18' && *end <= '\x1F')
140140
end += sizeof(void*);
141141
++end;
142142
}

lib/IRGen/GenKeyPath.cpp

Lines changed: 9 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -657,7 +657,7 @@ emitGeneratorForKeyPath(IRGenModule &IGM,
657657
ArrayRef<GenericRequirement> requirements,
658658
llvm::function_ref<void(IRGenFunction&,CanType)> emit) {
659659

660-
return IGM.getAddrOfStringForMetadataRef(name,
660+
return IGM.getAddrOfStringForMetadataRef(name, /*alignment=*/2,
661661
/*shouldSetLowBit=*/true,
662662
[&](ConstantInitBuilder &B) {
663663
// Build a stub that loads the necessary bindings from the key path's
@@ -707,34 +707,11 @@ emitMetadataGeneratorForKeyPath(IRGenModule &IGM,
707707
CanType type,
708708
GenericEnvironment *genericEnv,
709709
ArrayRef<GenericRequirement> requirements) {
710-
// If we have a non-dependent type, use a normal mangled type name.
711-
if (!type->hasTypeParameter()) {
712-
auto constant = IGM.getTypeRef(type, MangledTypeRefRole::Metadata);
713-
auto bitConstant = llvm::ConstantInt::get(IGM.IntPtrTy, 1);
714-
return llvm::ConstantExpr::getGetElementPtr(nullptr, constant, bitConstant);
715-
}
716-
717-
// Otherwise, create an accessor.
718-
CanGenericSignature genericSig;
719-
if (genericEnv)
720-
genericSig = genericEnv->getGenericSignature()->getCanonicalSignature();
721-
722-
IRGenMangler mangler;
723-
std::string symbolName =
724-
mangler.mangleSymbolNameForKeyPathMetadata(
725-
"keypath_get_type", genericSig, type,
726-
ProtocolConformanceRef::forInvalid());
727-
728-
// TODO: Use the standard metadata accessor when there are no arguments
729-
// and the metadata accessor is defined.
730-
return emitGeneratorForKeyPath(IGM, symbolName, type,
731-
IGM.TypeMetadataPtrTy,
732-
genericEnv, requirements,
733-
[&](IRGenFunction &IGF, CanType substType) {
734-
auto ret = IGF.emitTypeMetadataRef(substType);
735-
IGF.Builder.CreateRet(ret);
736-
});
737-
};
710+
// Produce a mangled name for the type.
711+
auto constant = IGM.getTypeRef(type, MangledTypeRefRole::Metadata);
712+
auto bitConstant = llvm::ConstantInt::get(IGM.IntPtrTy, 1);
713+
return llvm::ConstantExpr::getGetElementPtr(nullptr, constant, bitConstant);
714+
}
738715

739716
static llvm::Constant *
740717
emitWitnessTableGeneratorForKeyPath(IRGenModule &IGM,
@@ -1171,6 +1148,9 @@ IRGenModule::getAddrOfKeyPathPattern(KeyPathPattern *pattern,
11711148
fields.addInt32(0);
11721149
}
11731150

1151+
// Add the generic environment.
1152+
fields.addRelativeAddressOrNull(
1153+
getAddrOfGenericEnvironment(pattern->getGenericSignature()));
11741154
// Store type references for the root and leaf.
11751155
fields.addRelativeAddress(
11761156
emitMetadataGeneratorForKeyPath(*this, rootTy, genericEnv, requirements));

lib/IRGen/GenProto.cpp

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
#include "GenericRequirement.h"
6868
#include "IRGenDebugInfo.h"
6969
#include "IRGenFunction.h"
70+
#include "IRGenMangler.h"
7071
#include "IRGenModule.h"
7172
#include "MetadataPath.h"
7273
#include "MetadataRequest.h"
@@ -3419,3 +3420,58 @@ llvm::Value *irgen::emitProtocolDescriptorRef(IRGenFunction &IGF,
34193420

34203421
return val;
34213422
}
3423+
3424+
llvm::Constant *IRGenModule::getAddrOfGenericEnvironment(
3425+
CanGenericSignature signature) {
3426+
if (!signature)
3427+
return nullptr;
3428+
3429+
IRGenMangler mangler;
3430+
auto symbolName = mangler.mangleSymbolNameForGenericEnvironment(signature);
3431+
return getAddrOfStringForMetadataRef(symbolName, /*alignment=*/0, false,
3432+
[&] (ConstantInitBuilder &builder) -> ConstantInitFuture {
3433+
/// Collect the cumulative count of parameters at each level.
3434+
llvm::SmallVector<uint16_t, 4> genericParamCounts;
3435+
unsigned curDepth = 0;
3436+
unsigned genericParamCount = 0;
3437+
for (const auto gp : signature->getGenericParams()) {
3438+
if (curDepth != gp->getDepth()) {
3439+
genericParamCounts.push_back(genericParamCount);
3440+
curDepth = gp->getDepth();
3441+
}
3442+
3443+
++genericParamCount;
3444+
}
3445+
genericParamCounts.push_back(genericParamCount);
3446+
3447+
auto flags = GenericEnvironmentFlags()
3448+
.withNumGenericParameterLevels(genericParamCounts.size())
3449+
.withNumGenericRequirements(signature->getRequirements().size());
3450+
3451+
ConstantStructBuilder fields = builder.beginStruct();
3452+
fields.setPacked(true);
3453+
3454+
// Flags
3455+
fields.addInt32(flags.getIntValue());
3456+
3457+
// Parameter counts.
3458+
for (auto count : genericParamCounts) {
3459+
fields.addInt16(count);
3460+
}
3461+
3462+
// Generic parameters.
3463+
signature->forEachParam([&](GenericTypeParamType *param,
3464+
bool canonical) {
3465+
fields.addInt(Int8Ty,
3466+
GenericParamDescriptor(GenericParamKind::Type,
3467+
canonical,
3468+
false)
3469+
.getIntValue());
3470+
});
3471+
3472+
// Generic requirements
3473+
irgen::addGenericRequirements(*this, fields, signature,
3474+
signature->getRequirements());
3475+
return fields.finishAndCreateFuture();
3476+
});
3477+
}

lib/IRGen/IRGenMangler.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,3 +294,11 @@ std::string IRGenMangler::mangleSymbolNameForKeyPathMetadata(
294294
assert(conformance.isInvalid() && "Unknown protocol conformance");
295295
return finalize();
296296
}
297+
298+
std::string IRGenMangler::mangleSymbolNameForGenericEnvironment(
299+
CanGenericSignature genericSig) {
300+
beginManglingWithoutPrefix();
301+
Buffer << "generic environment ";
302+
appendGenericSignature(genericSig);
303+
return finalize();
304+
}

lib/IRGen/IRGenMangler.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,8 @@ class IRGenMangler : public Mangle::ASTMangler {
416416
CanType type,
417417
ProtocolConformanceRef conformance);
418418

419+
std::string mangleSymbolNameForGenericEnvironment(
420+
CanGenericSignature genericSig);
419421
protected:
420422
SymbolicMangling
421423
withSymbolicReferences(IRGenModule &IGM,

lib/IRGen/IRGenModule.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1032,6 +1032,7 @@ class IRGenModule {
10321032
///
10331033
/// \param symbolName The name of the symbol that describes the metadata
10341034
/// being referenced.
1035+
/// \param alignment If non-zero, the alignment of the requested variable.
10351036
/// \param shouldSetLowBit Whether to set the low bit of the result
10361037
/// constant, which is used by some clients to indicate that the result is
10371038
/// a mangled name.
@@ -1041,6 +1042,7 @@ class IRGenModule {
10411042
/// \returns the address of the global variable describing this metadata.
10421043
llvm::Constant *getAddrOfStringForMetadataRef(
10431044
StringRef symbolName,
1045+
unsigned alignment,
10441046
bool shouldSetLowBit,
10451047
llvm::function_ref<ConstantInitFuture(ConstantInitBuilder &)> body);
10461048

@@ -1276,6 +1278,7 @@ private: \
12761278
llvm::Constant *getAddrOfObjCModuleContextDescriptor();
12771279
llvm::Constant *getAddrOfClangImporterModuleContextDescriptor();
12781280
ConstantReference getAddrOfParentContextDescriptor(DeclContext *from);
1281+
llvm::Constant *getAddrOfGenericEnvironment(CanGenericSignature signature);
12791282
llvm::Constant *getAddrOfProtocolRequirementsBaseDescriptor(
12801283
ProtocolDecl *proto);
12811284
llvm::GlobalValue *defineProtocolRequirementsBaseDescriptor(

lib/IRGen/MetadataRequest.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,7 @@ MetadataDependency MetadataDependencyCollector::finish(IRGenFunction &IGF) {
220220

221221
llvm::Constant *IRGenModule::getAddrOfStringForMetadataRef(
222222
StringRef symbolName,
223+
unsigned alignment,
223224
bool shouldSetLowBit,
224225
llvm::function_ref<ConstantInitFuture (ConstantInitBuilder &)> body) {
225226
// Call this to form the return value.
@@ -251,7 +252,8 @@ llvm::Constant *IRGenModule::getAddrOfStringForMetadataRef(
251252
llvm::GlobalValue::HiddenVisibility,
252253
llvm::GlobalValue::DefaultStorageClass})
253254
.to(var);
254-
var->setAlignment(2);
255+
if (alignment)
256+
var->setAlignment(alignment);
255257
setTrueConstGlobal(var);
256258
var->setSection(getReflectionTypeRefSectionName());
257259

0 commit comments

Comments
 (0)