Skip to content

Mangle the protocol requirement array #15558

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Mar 28, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions include/swift/Basic/RelativePointer.h
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,54 @@ static inline Offset measureRelativeOffset(A *referent, B *base) {

} // namespace detail

/// A relative reference to an object stored in memory. The reference may be
/// direct or indirect, and uses the low bit of the (assumed at least
/// 2-byte-aligned) pointer to differentiate.
template<typename ValueTy, bool Nullable = false, typename Offset = int32_t>
class RelativeIndirectPointer {
private:
static_assert(std::is_integral<Offset>::value &&
std::is_signed<Offset>::value,
"offset type should be signed integer");

/// The relative offset of the pointer's memory from the `this` pointer.
/// This is an indirect reference.
Offset RelativeOffset;

/// RelativePointers should appear in statically-generated metadata. They
/// shouldn't be constructed or copied.
RelativeIndirectPointer() = delete;
RelativeIndirectPointer(RelativeIndirectPointer &&) = delete;
RelativeIndirectPointer(const RelativeIndirectPointer &) = delete;
RelativeIndirectPointer &operator=(RelativeIndirectPointer &&)
= delete;
RelativeIndirectPointer &operator=(const RelativeIndirectPointer &)
= delete;

public:
const ValueTy *get() const & {
// Check for null.
if (Nullable && RelativeOffset == 0)
return nullptr;

uintptr_t address = detail::applyRelativeOffset(this, RelativeOffset);
return *reinterpret_cast<const ValueTy * const *>(address);
}

/// A zero relative offset encodes a null reference.
bool isNull() const & {
return RelativeOffset == 0;
}

operator const ValueTy* () const & {
return get();
}

const ValueTy *operator->() const & {
return get();
}
};

/// A relative reference to an object stored in memory. The reference may be
/// direct or indirect, and uses the low bit of the (assumed at least
/// 2-byte-aligned) pointer to differentiate.
Expand Down
1 change: 1 addition & 0 deletions include/swift/Demangling/DemangleNodes.def
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ NODE(PropertyDescriptor)
CONTEXT_NODE(Protocol)
NODE(ProtocolConformance)
NODE(ProtocolDescriptor)
NODE(ProtocolRequirementArray)
NODE(ProtocolConformanceDescriptor)
NODE(ProtocolList)
NODE(ProtocolListWithClass)
Expand Down
14 changes: 12 additions & 2 deletions include/swift/IRGen/Linking.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,11 +169,15 @@ class LinkEntity {
/// The module descriptor for a module.
/// The pointer is a ModuleDecl*.
ModuleDescriptor,

/// The protocol descriptor for a protocol type.
/// The pointer is a ProtocolDecl*.
ProtocolDescriptor,

/// An array of protocol requirement descriptors for a protocol.
/// The pointer is a ProtocolDecl*.
ProtocolRequirementArray,

/// A SIL function. The pointer is a SILFunction*.
SILFunction,

Expand Down Expand Up @@ -280,7 +284,7 @@ class LinkEntity {
}

static bool isDeclKind(Kind k) {
return k <= Kind::ProtocolDescriptor;
return k <= Kind::ProtocolRequirementArray;
}
static bool isTypeKind(Kind k) {
return k >= Kind::ProtocolWitnessTableLazyAccessFunction;
Expand Down Expand Up @@ -567,6 +571,12 @@ class LinkEntity {
return entity;
}

static LinkEntity forProtocolRequirementArray(ProtocolDecl *decl) {
LinkEntity entity;
entity.setForDecl(Kind::ProtocolRequirementArray, decl);
return entity;
}

static LinkEntity forValueWitness(CanType concreteType, ValueWitness witness) {
LinkEntity entity;
entity.Pointer = concreteType.getPointer();
Expand Down
5 changes: 5 additions & 0 deletions lib/Demangling/Demangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2079,6 +2079,11 @@ NodePointer Demangler::demangleWitness() {
return createWithChild(
Node::Kind::GenericProtocolWitnessTableInstantiationFunction,
popProtocolConformance());

case 'R':
return createWithChild(Node::Kind::ProtocolRequirementArray,
popProtocol());

case 'l': {
NodePointer Conf = popProtocolConformance();
NodePointer Type = popNode(Node::Kind::Type);
Expand Down
5 changes: 5 additions & 0 deletions lib/Demangling/NodePrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,7 @@ class NodePrinter {
case Node::Kind::ProtocolConformance:
case Node::Kind::ProtocolConformanceDescriptor:
case Node::Kind::ProtocolDescriptor:
case Node::Kind::ProtocolRequirementArray:
case Node::Kind::ProtocolWitness:
case Node::Kind::ProtocolWitnessTable:
case Node::Kind::ProtocolWitnessTableAccessor:
Expand Down Expand Up @@ -1453,6 +1454,10 @@ NodePointer NodePrinter::print(NodePointer Node, bool asPrefixContext) {
Printer << "protocol descriptor for ";
print(Node->getChild(0));
return nullptr;
case Node::Kind::ProtocolRequirementArray:
Printer << "protocol requirement array for ";
print(Node->getChild(0));
return nullptr;
case Node::Kind::FullTypeMetadata:
Printer << "full type metadata for ";
print(Node->getChild(0));
Expand Down
4 changes: 4 additions & 0 deletions lib/Demangling/OldRemangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -756,6 +756,10 @@ void Remangler::mangleProtocolDescriptor(Node *node) {
mangleProtocolWithoutPrefix(node->begin()[0]);
}

void Remangler::mangleProtocolRequirementArray(Node *node) {
unreachable("todo");
}

void Remangler::mangleProtocolConformanceDescriptor(Node *node) {
Out << "Mc";
mangleProtocolConformance(node->begin()[0]);
Expand Down
5 changes: 5 additions & 0 deletions lib/Demangling/Remangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1508,6 +1508,11 @@ void Remangler::mangleProtocolDescriptor(Node *node) {
Buffer << "Mp";
}

void Remangler::mangleProtocolRequirementArray(Node *node) {
manglePureProtocol(getSingleChild(node));
Buffer << "WR";
}

void Remangler::mangleProtocolConformanceDescriptor(Node *node) {
mangleProtocolConformance(node->getChild(0));
Buffer << "Mc";
Expand Down
9 changes: 9 additions & 0 deletions lib/IRGen/ConstantBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,15 @@ class ConstantAggregateBuilderBase
unsigned(reference.isIndirect()));
}

/// Add an indirect relative reference to the given address.
/// The target must be a "GOT-equivalent", i.e. a pointer to an
/// external object.
void addIndirectRelativeAddress(ConstantReference reference) {
assert(reference.isIndirect());
addRelativeOffset(IGM().RelativeAddressTy,
reference.getValue());
}

Size getNextOffsetFromGlobal() const {
return Size(super::getNextOffsetFromGlobal().getQuantity());
}
Expand Down
13 changes: 13 additions & 0 deletions lib/IRGen/GenDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/SaveAndRestore.h"
#include "llvm/Transforms/Utils/ModuleUtils.h"

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

case Kind::ProtocolRequirementArray:
return SILLinkage::Private;

case Kind::DirectProtocolWitnessTable:
case Kind::ProtocolWitnessTableAccessFunction:
case Kind::ProtocolConformanceDescriptor:
Expand Down Expand Up @@ -1658,6 +1662,7 @@ bool LinkEntity::isAvailableExternally(IRGenModule &IGM) const {
case Kind::PropertyDescriptor:
case Kind::NominalTypeDescriptor:
case Kind::ProtocolDescriptor:
case Kind::ProtocolRequirementArray:
return ::isAvailableExternally(IGM, getDecl());

case Kind::EnumCase:
Expand Down Expand Up @@ -3489,6 +3494,14 @@ llvm::Constant *IRGenModule::getAddrOfProtocolDescriptor(ProtocolDecl *D,
ProtocolDescriptorStructTy, DebugTypeInfo());
}

llvm::Constant *IRGenModule::getAddrOfProtocolRequirementArray(ProtocolDecl *D,
ConstantInit definition) {
auto entity = LinkEntity::forProtocolRequirementArray(D);
return getAddrOfLLVMVariable(entity, Alignment(4), definition,
definition.getType(),
DebugTypeInfo());
}

llvm::Constant *IRGenModule::getAddrOfProtocolConformanceDescriptor(
const NormalProtocolConformance *conformance,
ConstantInit definition) {
Expand Down
8 changes: 5 additions & 3 deletions lib/IRGen/GenMeta.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3619,10 +3619,12 @@ namespace {
#endif

auto global =
reqtsArray.finishAndCreateGlobal("", Alignment(4), /*constant*/ true,
llvm::GlobalVariable::InternalLinkage);
global->setUnnamedAddr(llvm::GlobalVariable::UnnamedAddr::Global);
cast<llvm::GlobalVariable>(
IGM.getAddrOfProtocolRequirementArray(Protocol,
reqtsArray.finishAndCreateFuture()));
global->setConstant(true);
B.addRelativeOffset(IGM.Int32Ty, global);
IGM.setTrueConstGlobal(global);
}

struct RequirementInfo {
Expand Down
2 changes: 2 additions & 0 deletions lib/IRGen/IRGenMangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
#include "swift/Demangling/ManglingMacros.h"
#include "swift/Demangling/Demangle.h"
#include "swift/ABI/MetadataValues.h"
#include "swift/ClangImporter/ClangModule.h"
#include "llvm/Support/SaveAndRestore.h"

using namespace swift;
using namespace irgen;
Expand Down
17 changes: 12 additions & 5 deletions lib/IRGen/IRGenMangler.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@
#define SWIFT_IRGEN_IRGENMANGLER_H

#include "IRGenModule.h"
#include "llvm/Support/SaveAndRestore.h"
#include "swift/AST/ASTMangler.h"
#include "swift/AST/GenericEnvironment.h"
#include "swift/AST/ProtocolConformance.h"
#include "swift/ClangImporter/ClangModule.h"
#include "swift/IRGen/ValueWitness.h"

namespace swift {

class ProtocolConformance;
class NormalProtocolConformance;

namespace irgen {

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

std::string mangleProtocolRequirementArray(const ProtocolDecl *Decl) {
beginMangling();
appendProtocolName(Decl);
appendOperator("WR");
return finalize();
}

std::string mangleProtocolConformanceDescriptor(
const NormalProtocolConformance *Conformance) {
const ProtocolConformance *Conformance) {
beginMangling();
appendProtocolConformance(Conformance);
appendOperator("Mc");
Expand Down
2 changes: 2 additions & 0 deletions lib/IRGen/IRGenModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -1171,6 +1171,8 @@ private: \
ConstantReference getAddrOfParentContextDescriptor(DeclContext *from);
llvm::Constant *getAddrOfProtocolDescriptor(ProtocolDecl *D,
ConstantInit definition = ConstantInit());
llvm::Constant *getAddrOfProtocolRequirementArray(ProtocolDecl *D,
ConstantInit definition);
llvm::Constant *getAddrOfProtocolConformanceDescriptor(
const NormalProtocolConformance *conformance,
ConstantInit definition = ConstantInit());
Expand Down
3 changes: 3 additions & 0 deletions lib/IRGen/Linking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,9 @@ std::string LinkEntity::mangleAsString() const {
case Kind::ProtocolDescriptor:
return mangler.mangleProtocolDescriptor(cast<ProtocolDecl>(getDecl()));

case Kind::ProtocolRequirementArray:
return mangler.mangleProtocolRequirementArray(cast<ProtocolDecl>(getDecl()));

case Kind::ProtocolConformanceDescriptor:
return mangler.mangleProtocolConformanceDescriptor(
cast<NormalProtocolConformance>(getProtocolConformance()));
Expand Down
2 changes: 2 additions & 0 deletions lib/IRGen/MetadataRequest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
#include "swift/AST/ASTContext.h"
#include "swift/AST/ExistentialLayout.h"
#include "swift/AST/IRGenOptions.h"
#include "swift/AST/SubstitutionMap.h"
#include "swift/ClangImporter/ClangModule.h"
#include "swift/SIL/FormalLinkage.h"
#include "swift/SIL/TypeLowering.h"

Expand Down
16 changes: 8 additions & 8 deletions test/IRGen/protocol_metadata.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,20 @@ protocol ABO : A, B, O { func abo() }
// -- flags: 1 = Swift | 2 = Not Class-Constrained | 4 = Needs Witness Table
// CHECK-SAME: i32 72, i32 7,
// CHECK-SAME: i16 1, i16 1,
// 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)
// 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)
// CHECK-SAME: }

// CHECK: @"$S17protocol_metadata1BMp" = hidden constant %swift.protocol {
// CHECK-SAME: i32 72, i32 7,
// CHECK-SAME: i16 1, i16 1,
// 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)
// 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)
// CHECK: }

// CHECK: @"$S17protocol_metadata1CMp" = hidden constant %swift.protocol {
// -- flags: 1 = Swift | 4 = Needs Witness Table
// CHECK-SAME: i32 72, i32 5,
// CHECK-SAME: i16 1, i16 1,
// 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)
// 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)
// CHECK-SAME: }

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

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

// -- @objc protocol OPT uses ObjC symbol mangling and layout
// CHECK: @_PROTOCOL__TtP17protocol_metadata3OPT_ = private constant { {{.*}} i32, [4 x i8*]*, i8*, i8* } {
Expand All @@ -67,7 +67,7 @@ protocol ABO : A, B, O { func abo() }
// CHECK: %swift.protocol* @"$S17protocol_metadata1AMp",
// CHECK: %swift.protocol* @"$S17protocol_metadata1BMp"
// CHECK: }
// 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 }]
// 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 }]
// CHECK: @"$S17protocol_metadata2ABMp" = hidden constant %swift.protocol {
// CHECK-SAME: [[AB_INHERITED]]
// CHECK-SAME: i32 72, i32 7,
Expand All @@ -91,7 +91,7 @@ protocol Comprehensive {
static var global: Assoc { get set }
}

// CHECK: [[COMPREHENSIVE_REQTS:@.*]] = internal unnamed_addr constant [11 x %swift.protocol_requirement]
// CHECK: [[COMPREHENSIVE_REQTS:@".*"]] = internal constant [11 x %swift.protocol_requirement]
// CHECK-SAME: [%swift.protocol_requirement { i32 6, i32 0, i32 0 },
// CHECK-SAME: %swift.protocol_requirement { i32 7, i32 0, i32 0 },
// CHECK-SAME: %swift.protocol_requirement { i32 2, i32 0, i32 0 },
Expand Down
2 changes: 1 addition & 1 deletion test/IRGen/protocol_resilience.sil
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import resilient_protocol

// Protocol is public -- needs resilient witness table

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

Expand Down