Skip to content

Commit 4c6b452

Browse files
authored
Merge pull request #15558 from slavapestov/protocol-requirement-array
Mangle the protocol requirement array
2 parents 543b543 + e7ac4f5 commit 4c6b452

17 files changed

+137
-19
lines changed

include/swift/Basic/RelativePointer.h

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,54 @@ static inline Offset measureRelativeOffset(A *referent, B *base) {
175175

176176
} // namespace detail
177177

178+
/// A relative reference to an object stored in memory. The reference may be
179+
/// direct or indirect, and uses the low bit of the (assumed at least
180+
/// 2-byte-aligned) pointer to differentiate.
181+
template<typename ValueTy, bool Nullable = false, typename Offset = int32_t>
182+
class RelativeIndirectPointer {
183+
private:
184+
static_assert(std::is_integral<Offset>::value &&
185+
std::is_signed<Offset>::value,
186+
"offset type should be signed integer");
187+
188+
/// The relative offset of the pointer's memory from the `this` pointer.
189+
/// This is an indirect reference.
190+
Offset RelativeOffset;
191+
192+
/// RelativePointers should appear in statically-generated metadata. They
193+
/// shouldn't be constructed or copied.
194+
RelativeIndirectPointer() = delete;
195+
RelativeIndirectPointer(RelativeIndirectPointer &&) = delete;
196+
RelativeIndirectPointer(const RelativeIndirectPointer &) = delete;
197+
RelativeIndirectPointer &operator=(RelativeIndirectPointer &&)
198+
= delete;
199+
RelativeIndirectPointer &operator=(const RelativeIndirectPointer &)
200+
= delete;
201+
202+
public:
203+
const ValueTy *get() const & {
204+
// Check for null.
205+
if (Nullable && RelativeOffset == 0)
206+
return nullptr;
207+
208+
uintptr_t address = detail::applyRelativeOffset(this, RelativeOffset);
209+
return *reinterpret_cast<const ValueTy * const *>(address);
210+
}
211+
212+
/// A zero relative offset encodes a null reference.
213+
bool isNull() const & {
214+
return RelativeOffset == 0;
215+
}
216+
217+
operator const ValueTy* () const & {
218+
return get();
219+
}
220+
221+
const ValueTy *operator->() const & {
222+
return get();
223+
}
224+
};
225+
178226
/// A relative reference to an object stored in memory. The reference may be
179227
/// direct or indirect, and uses the low bit of the (assumed at least
180228
/// 2-byte-aligned) pointer to differentiate.

include/swift/Demangling/DemangleNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ NODE(PropertyDescriptor)
137137
CONTEXT_NODE(Protocol)
138138
NODE(ProtocolConformance)
139139
NODE(ProtocolDescriptor)
140+
NODE(ProtocolRequirementArray)
140141
NODE(ProtocolConformanceDescriptor)
141142
NODE(ProtocolList)
142143
NODE(ProtocolListWithClass)

include/swift/IRGen/Linking.h

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,11 +169,15 @@ class LinkEntity {
169169
/// The module descriptor for a module.
170170
/// The pointer is a ModuleDecl*.
171171
ModuleDescriptor,
172-
172+
173173
/// The protocol descriptor for a protocol type.
174174
/// The pointer is a ProtocolDecl*.
175175
ProtocolDescriptor,
176176

177+
/// An array of protocol requirement descriptors for a protocol.
178+
/// The pointer is a ProtocolDecl*.
179+
ProtocolRequirementArray,
180+
177181
/// A SIL function. The pointer is a SILFunction*.
178182
SILFunction,
179183

@@ -280,7 +284,7 @@ class LinkEntity {
280284
}
281285

282286
static bool isDeclKind(Kind k) {
283-
return k <= Kind::ProtocolDescriptor;
287+
return k <= Kind::ProtocolRequirementArray;
284288
}
285289
static bool isTypeKind(Kind k) {
286290
return k >= Kind::ProtocolWitnessTableLazyAccessFunction;
@@ -567,6 +571,12 @@ class LinkEntity {
567571
return entity;
568572
}
569573

574+
static LinkEntity forProtocolRequirementArray(ProtocolDecl *decl) {
575+
LinkEntity entity;
576+
entity.setForDecl(Kind::ProtocolRequirementArray, decl);
577+
return entity;
578+
}
579+
570580
static LinkEntity forValueWitness(CanType concreteType, ValueWitness witness) {
571581
LinkEntity entity;
572582
entity.Pointer = concreteType.getPointer();

lib/Demangling/Demangler.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2079,6 +2079,11 @@ NodePointer Demangler::demangleWitness() {
20792079
return createWithChild(
20802080
Node::Kind::GenericProtocolWitnessTableInstantiationFunction,
20812081
popProtocolConformance());
2082+
2083+
case 'R':
2084+
return createWithChild(Node::Kind::ProtocolRequirementArray,
2085+
popProtocol());
2086+
20822087
case 'l': {
20832088
NodePointer Conf = popProtocolConformance();
20842089
NodePointer Type = popNode(Node::Kind::Type);

lib/Demangling/NodePrinter.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,7 @@ class NodePrinter {
399399
case Node::Kind::ProtocolConformance:
400400
case Node::Kind::ProtocolConformanceDescriptor:
401401
case Node::Kind::ProtocolDescriptor:
402+
case Node::Kind::ProtocolRequirementArray:
402403
case Node::Kind::ProtocolWitness:
403404
case Node::Kind::ProtocolWitnessTable:
404405
case Node::Kind::ProtocolWitnessTableAccessor:
@@ -1453,6 +1454,10 @@ NodePointer NodePrinter::print(NodePointer Node, bool asPrefixContext) {
14531454
Printer << "protocol descriptor for ";
14541455
print(Node->getChild(0));
14551456
return nullptr;
1457+
case Node::Kind::ProtocolRequirementArray:
1458+
Printer << "protocol requirement array for ";
1459+
print(Node->getChild(0));
1460+
return nullptr;
14561461
case Node::Kind::FullTypeMetadata:
14571462
Printer << "full type metadata for ";
14581463
print(Node->getChild(0));

lib/Demangling/OldRemangler.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -756,6 +756,10 @@ void Remangler::mangleProtocolDescriptor(Node *node) {
756756
mangleProtocolWithoutPrefix(node->begin()[0]);
757757
}
758758

759+
void Remangler::mangleProtocolRequirementArray(Node *node) {
760+
unreachable("todo");
761+
}
762+
759763
void Remangler::mangleProtocolConformanceDescriptor(Node *node) {
760764
Out << "Mc";
761765
mangleProtocolConformance(node->begin()[0]);

lib/Demangling/Remangler.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1508,6 +1508,11 @@ void Remangler::mangleProtocolDescriptor(Node *node) {
15081508
Buffer << "Mp";
15091509
}
15101510

1511+
void Remangler::mangleProtocolRequirementArray(Node *node) {
1512+
manglePureProtocol(getSingleChild(node));
1513+
Buffer << "WR";
1514+
}
1515+
15111516
void Remangler::mangleProtocolConformanceDescriptor(Node *node) {
15121517
mangleProtocolConformance(node->getChild(0));
15131518
Buffer << "Mc";

lib/IRGen/ConstantBuilder.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,15 @@ class ConstantAggregateBuilderBase
9494
unsigned(reference.isIndirect()));
9595
}
9696

97+
/// Add an indirect relative reference to the given address.
98+
/// The target must be a "GOT-equivalent", i.e. a pointer to an
99+
/// external object.
100+
void addIndirectRelativeAddress(ConstantReference reference) {
101+
assert(reference.isIndirect());
102+
addRelativeOffset(IGM().RelativeAddressTy,
103+
reference.getValue());
104+
}
105+
97106
Size getNextOffsetFromGlobal() const {
98107
return Size(super::getNextOffsetFromGlobal().getQuantity());
99108
}

lib/IRGen/GenDecl.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
#include "llvm/Support/Compiler.h"
4848
#include "llvm/Support/ConvertUTF.h"
4949
#include "llvm/Support/Path.h"
50+
#include "llvm/Support/SaveAndRestore.h"
5051
#include "llvm/Transforms/Utils/ModuleUtils.h"
5152

5253
#include "ConstantBuilder.h"
@@ -1557,6 +1558,9 @@ SILLinkage LinkEntity::getLinkage(ForDefinition_t forDefinition) const {
15571558
case Kind::ProtocolDescriptor:
15581559
return getSILLinkage(getDeclLinkage(getDecl()), forDefinition);
15591560

1561+
case Kind::ProtocolRequirementArray:
1562+
return SILLinkage::Private;
1563+
15601564
case Kind::DirectProtocolWitnessTable:
15611565
case Kind::ProtocolWitnessTableAccessFunction:
15621566
case Kind::ProtocolConformanceDescriptor:
@@ -1658,6 +1662,7 @@ bool LinkEntity::isAvailableExternally(IRGenModule &IGM) const {
16581662
case Kind::PropertyDescriptor:
16591663
case Kind::NominalTypeDescriptor:
16601664
case Kind::ProtocolDescriptor:
1665+
case Kind::ProtocolRequirementArray:
16611666
return ::isAvailableExternally(IGM, getDecl());
16621667

16631668
case Kind::EnumCase:
@@ -3489,6 +3494,14 @@ llvm::Constant *IRGenModule::getAddrOfProtocolDescriptor(ProtocolDecl *D,
34893494
ProtocolDescriptorStructTy, DebugTypeInfo());
34903495
}
34913496

3497+
llvm::Constant *IRGenModule::getAddrOfProtocolRequirementArray(ProtocolDecl *D,
3498+
ConstantInit definition) {
3499+
auto entity = LinkEntity::forProtocolRequirementArray(D);
3500+
return getAddrOfLLVMVariable(entity, Alignment(4), definition,
3501+
definition.getType(),
3502+
DebugTypeInfo());
3503+
}
3504+
34923505
llvm::Constant *IRGenModule::getAddrOfProtocolConformanceDescriptor(
34933506
const NormalProtocolConformance *conformance,
34943507
ConstantInit definition) {

lib/IRGen/GenMeta.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3619,10 +3619,12 @@ namespace {
36193619
#endif
36203620

36213621
auto global =
3622-
reqtsArray.finishAndCreateGlobal("", Alignment(4), /*constant*/ true,
3623-
llvm::GlobalVariable::InternalLinkage);
3624-
global->setUnnamedAddr(llvm::GlobalVariable::UnnamedAddr::Global);
3622+
cast<llvm::GlobalVariable>(
3623+
IGM.getAddrOfProtocolRequirementArray(Protocol,
3624+
reqtsArray.finishAndCreateFuture()));
3625+
global->setConstant(true);
36253626
B.addRelativeOffset(IGM.Int32Ty, global);
3627+
IGM.setTrueConstGlobal(global);
36263628
}
36273629

36283630
struct RequirementInfo {

lib/IRGen/IRGenMangler.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
#include "swift/Demangling/ManglingMacros.h"
1717
#include "swift/Demangling/Demangle.h"
1818
#include "swift/ABI/MetadataValues.h"
19+
#include "swift/ClangImporter/ClangModule.h"
20+
#include "llvm/Support/SaveAndRestore.h"
1921

2022
using namespace swift;
2123
using namespace irgen;

lib/IRGen/IRGenMangler.h

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,14 @@
1414
#define SWIFT_IRGEN_IRGENMANGLER_H
1515

1616
#include "IRGenModule.h"
17-
#include "llvm/Support/SaveAndRestore.h"
1817
#include "swift/AST/ASTMangler.h"
19-
#include "swift/AST/GenericEnvironment.h"
20-
#include "swift/AST/ProtocolConformance.h"
21-
#include "swift/ClangImporter/ClangModule.h"
2218
#include "swift/IRGen/ValueWitness.h"
2319

2420
namespace swift {
21+
22+
class ProtocolConformance;
23+
class NormalProtocolConformance;
24+
2525
namespace irgen {
2626

2727
/// A mangling string that includes embedded symbolic references.
@@ -121,8 +121,15 @@ class IRGenMangler : public Mangle::ASTMangler {
121121
return finalize();
122122
}
123123

124+
std::string mangleProtocolRequirementArray(const ProtocolDecl *Decl) {
125+
beginMangling();
126+
appendProtocolName(Decl);
127+
appendOperator("WR");
128+
return finalize();
129+
}
130+
124131
std::string mangleProtocolConformanceDescriptor(
125-
const NormalProtocolConformance *Conformance) {
132+
const ProtocolConformance *Conformance) {
126133
beginMangling();
127134
appendProtocolConformance(Conformance);
128135
appendOperator("Mc");

lib/IRGen/IRGenModule.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1171,6 +1171,8 @@ private: \
11711171
ConstantReference getAddrOfParentContextDescriptor(DeclContext *from);
11721172
llvm::Constant *getAddrOfProtocolDescriptor(ProtocolDecl *D,
11731173
ConstantInit definition = ConstantInit());
1174+
llvm::Constant *getAddrOfProtocolRequirementArray(ProtocolDecl *D,
1175+
ConstantInit definition);
11741176
llvm::Constant *getAddrOfProtocolConformanceDescriptor(
11751177
const NormalProtocolConformance *conformance,
11761178
ConstantInit definition = ConstantInit());

lib/IRGen/Linking.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,9 @@ std::string LinkEntity::mangleAsString() const {
142142
case Kind::ProtocolDescriptor:
143143
return mangler.mangleProtocolDescriptor(cast<ProtocolDecl>(getDecl()));
144144

145+
case Kind::ProtocolRequirementArray:
146+
return mangler.mangleProtocolRequirementArray(cast<ProtocolDecl>(getDecl()));
147+
145148
case Kind::ProtocolConformanceDescriptor:
146149
return mangler.mangleProtocolConformanceDescriptor(
147150
cast<NormalProtocolConformance>(getProtocolConformance()));

lib/IRGen/MetadataRequest.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
#include "swift/AST/ASTContext.h"
3333
#include "swift/AST/ExistentialLayout.h"
3434
#include "swift/AST/IRGenOptions.h"
35+
#include "swift/AST/SubstitutionMap.h"
36+
#include "swift/ClangImporter/ClangModule.h"
3537
#include "swift/SIL/FormalLinkage.h"
3638
#include "swift/SIL/TypeLowering.h"
3739

test/IRGen/protocol_metadata.swift

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,20 +23,20 @@ protocol ABO : A, B, O { func abo() }
2323
// -- flags: 1 = Swift | 2 = Not Class-Constrained | 4 = Needs Witness Table
2424
// CHECK-SAME: i32 72, i32 7,
2525
// CHECK-SAME: i16 1, i16 1,
26-
// CHECK-SAME: i32 trunc (i64 sub (i64 ptrtoint ([1 x %swift.protocol_requirement]* [[A_REQTS:@.*]] to i64), i64 ptrtoint (i32* getelementptr inbounds (%swift.protocol, %swift.protocol* @"$S17protocol_metadata1AMp", i32 0, i32 12) to i64)) to i32)
26+
// CHECK-SAME: i32 trunc (i64 sub (i64 ptrtoint ([1 x %swift.protocol_requirement]* [[A_REQTS:@".*"]] to i64), i64 ptrtoint (i32* getelementptr inbounds (%swift.protocol, %swift.protocol* @"$S17protocol_metadata1AMp", i32 0, i32 12) to i64)) to i32)
2727
// CHECK-SAME: }
2828

2929
// CHECK: @"$S17protocol_metadata1BMp" = hidden constant %swift.protocol {
3030
// CHECK-SAME: i32 72, i32 7,
3131
// CHECK-SAME: i16 1, i16 1,
32-
// CHECK-SAME: i32 trunc (i64 sub (i64 ptrtoint ([1 x %swift.protocol_requirement]* [[B_REQTS:@.*]] to i64), i64 ptrtoint (i32* getelementptr inbounds (%swift.protocol, %swift.protocol* @"$S17protocol_metadata1BMp", i32 0, i32 12) to i64)) to i32)
32+
// CHECK-SAME: i32 trunc (i64 sub (i64 ptrtoint ([1 x %swift.protocol_requirement]* [[B_REQTS:@".*"]] to i64), i64 ptrtoint (i32* getelementptr inbounds (%swift.protocol, %swift.protocol* @"$S17protocol_metadata1BMp", i32 0, i32 12) to i64)) to i32)
3333
// CHECK: }
3434

3535
// CHECK: @"$S17protocol_metadata1CMp" = hidden constant %swift.protocol {
3636
// -- flags: 1 = Swift | 4 = Needs Witness Table
3737
// CHECK-SAME: i32 72, i32 5,
3838
// CHECK-SAME: i16 1, i16 1,
39-
// CHECK-SAME: i32 trunc (i64 sub (i64 ptrtoint ([1 x %swift.protocol_requirement]* [[C_REQTS:@.*]] to i64), i64 ptrtoint (i32* getelementptr inbounds (%swift.protocol, %swift.protocol* @"$S17protocol_metadata1CMp", i32 0, i32 12) to i64)) to i32)
39+
// CHECK-SAME: i32 trunc (i64 sub (i64 ptrtoint ([1 x %swift.protocol_requirement]* [[C_REQTS:@".*"]] to i64), i64 ptrtoint (i32* getelementptr inbounds (%swift.protocol, %swift.protocol* @"$S17protocol_metadata1CMp", i32 0, i32 12) to i64)) to i32)
4040
// CHECK-SAME: }
4141

4242
// -- @objc protocol O uses ObjC symbol mangling and layout
@@ -47,9 +47,9 @@ protocol ABO : A, B, O { func abo() }
4747
// CHECK-SAME: @_PROTOCOL_METHOD_TYPES__TtP17protocol_metadata1O_
4848
// CHECK-SAME: }
4949

50-
// CHECK: [[A_REQTS]] = internal unnamed_addr constant [1 x %swift.protocol_requirement] [%swift.protocol_requirement { i32 17, i32 0, i32 0 }]
51-
// CHECK: [[B_REQTS]] = internal unnamed_addr constant [1 x %swift.protocol_requirement] [%swift.protocol_requirement { i32 17, i32 0, i32 0 }]
52-
// CHECK: [[C_REQTS]] = internal unnamed_addr constant [1 x %swift.protocol_requirement] [%swift.protocol_requirement { i32 17, i32 0, i32 0 }]
50+
// CHECK: [[A_REQTS]] = internal constant [1 x %swift.protocol_requirement] [%swift.protocol_requirement { i32 17, i32 0, i32 0 }]
51+
// CHECK: [[B_REQTS]] = internal constant [1 x %swift.protocol_requirement] [%swift.protocol_requirement { i32 17, i32 0, i32 0 }]
52+
// CHECK: [[C_REQTS]] = internal constant [1 x %swift.protocol_requirement] [%swift.protocol_requirement { i32 17, i32 0, i32 0 }]
5353

5454
// -- @objc protocol OPT uses ObjC symbol mangling and layout
5555
// CHECK: @_PROTOCOL__TtP17protocol_metadata3OPT_ = private constant { {{.*}} i32, [4 x i8*]*, i8*, i8* } {
@@ -67,7 +67,7 @@ protocol ABO : A, B, O { func abo() }
6767
// CHECK: %swift.protocol* @"$S17protocol_metadata1AMp",
6868
// CHECK: %swift.protocol* @"$S17protocol_metadata1BMp"
6969
// CHECK: }
70-
// CHECK: [[AB_REQTS:@.*]] = internal unnamed_addr constant [3 x %swift.protocol_requirement] [%swift.protocol_requirement zeroinitializer, %swift.protocol_requirement zeroinitializer, %swift.protocol_requirement { i32 17, i32 0, i32 0 }]
70+
// CHECK: [[AB_REQTS:@".*"]] = internal constant [3 x %swift.protocol_requirement] [%swift.protocol_requirement zeroinitializer, %swift.protocol_requirement zeroinitializer, %swift.protocol_requirement { i32 17, i32 0, i32 0 }]
7171
// CHECK: @"$S17protocol_metadata2ABMp" = hidden constant %swift.protocol {
7272
// CHECK-SAME: [[AB_INHERITED]]
7373
// CHECK-SAME: i32 72, i32 7,
@@ -91,7 +91,7 @@ protocol Comprehensive {
9191
static var global: Assoc { get set }
9292
}
9393

94-
// CHECK: [[COMPREHENSIVE_REQTS:@.*]] = internal unnamed_addr constant [11 x %swift.protocol_requirement]
94+
// CHECK: [[COMPREHENSIVE_REQTS:@".*"]] = internal constant [11 x %swift.protocol_requirement]
9595
// CHECK-SAME: [%swift.protocol_requirement { i32 6, i32 0, i32 0 },
9696
// CHECK-SAME: %swift.protocol_requirement { i32 7, i32 0, i32 0 },
9797
// CHECK-SAME: %swift.protocol_requirement { i32 2, i32 0, i32 0 },

test/IRGen/protocol_resilience.sil

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import resilient_protocol
1414

1515
// Protocol is public -- needs resilient witness table
1616

17-
// CHECK: [[RP_REQTS:@.*]] = internal unnamed_addr constant [8 x %swift.protocol_requirement]
17+
// CHECK: [[RP_REQTS:@"\$S19protocol_resilience17ResilientProtocolWR"]] = internal constant [8 x %swift.protocol_requirement]
1818
// CHECK-SAME: [%swift.protocol_requirement { i32 6, i32 0, i32 0 },
1919
// CHECK-SAME: %swift.protocol_requirement { i32 7, i32 0, i32 0 },
2020

0 commit comments

Comments
 (0)