Skip to content

ASTMangler: use specified module names from @_originalDefinedIn to mangle symbols names #28528

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 1 commit into from
Dec 3, 2019
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
4 changes: 2 additions & 2 deletions include/swift/AST/ASTMangler.h
Original file line number Diff line number Diff line change
Expand Up @@ -253,9 +253,9 @@ class ASTMangler : public Mangler {

void appendContextOf(const ValueDecl *decl);

void appendContext(const DeclContext *ctx);
void appendContext(const DeclContext *ctx, StringRef useModuleName);

void appendModule(const ModuleDecl *module);
void appendModule(const ModuleDecl *module, StringRef useModuleName);

void appendProtocolName(const ProtocolDecl *protocol,
bool allowStandardSubstitution = true);
Expand Down
4 changes: 4 additions & 0 deletions include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -897,6 +897,10 @@ class alignas(1 << DeclAlignInBits) Decl {
/// If this returns true, the decl can be safely casted to ValueDecl.
bool isPotentiallyOverridable() const;

/// If an alternative module name is specified for this decl, e.g. using
/// @_originalDefinedIn attribute, this function returns this module name.
StringRef getAlternateModuleName() const;

/// Emit a diagnostic tied to this declaration.
template<typename ...ArgTypes>
InFlightDiagnostic diagnose(
Expand Down
63 changes: 39 additions & 24 deletions lib/AST/ASTMangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ std::string ASTMangler::mangleIVarInitDestroyEntity(const ClassDecl *decl,
bool isDestroyer,
SymbolKind SKind) {
beginMangling();
appendContext(decl);
appendContext(decl, decl->getAlternateModuleName());
appendOperator(isDestroyer ? "fE" : "fe");
appendSymbolKind(SKind);
return finalize();
Expand Down Expand Up @@ -436,7 +436,7 @@ std::string ASTMangler::mangleObjCRuntimeName(const NominalTypeDecl *Nominal) {
assert(isa<ProtocolDecl>(Nominal));
Buffer << 'P';
}
appendModule(Ctx->getParentModule());
appendModule(Ctx->getParentModule(), StringRef());
appendIdentifier(Nominal->getName().str());
if (isProto)
Buffer << '_';
Expand Down Expand Up @@ -479,7 +479,7 @@ std::string ASTMangler::mangleObjCRuntimeName(const NominalTypeDecl *Nominal) {
std::string ASTMangler::mangleTypeAsContextUSR(const NominalTypeDecl *type) {
beginManglingWithoutPrefix();
llvm::SaveAndRestore<bool> allowUnnamedRAII(AllowNamelessEntities, true);
appendContext(type);
appendContext(type, type->getAlternateModuleName());
return finalize();
}

Expand Down Expand Up @@ -1561,7 +1561,7 @@ void ASTMangler::appendContextOf(const ValueDecl *decl) {
}

// Just mangle the decl's DC.
appendContext(decl->getDeclContext());
appendContext(decl->getDeclContext(), decl->getAlternateModuleName());
}

namespace {
Expand Down Expand Up @@ -1617,14 +1617,14 @@ static Optional<VarDecl*> findFirstVariable(PatternBindingDecl *binding) {
return None;
}

void ASTMangler::appendContext(const DeclContext *ctx) {
void ASTMangler::appendContext(const DeclContext *ctx, StringRef useModuleName) {
switch (ctx->getContextKind()) {
case DeclContextKind::Module:
return appendModule(cast<ModuleDecl>(ctx));
return appendModule(cast<ModuleDecl>(ctx), useModuleName);

case DeclContextKind::FileUnit:
assert(!isa<BuiltinUnit>(ctx) && "mangling member of builtin module!");
appendContext(ctx->getParent());
appendContext(ctx->getParent(), useModuleName);
return;

case DeclContextKind::SerializedLocal: {
Expand All @@ -1645,12 +1645,12 @@ void ASTMangler::appendContext(const DeclContext *ctx) {
} else {
// This is incorrect in that it does not produce a /unique/ mangling,
// but it will at least produce a /valid/ mangling.
appendContext(ctx->getParent());
appendContext(ctx->getParent(), useModuleName);
}
return;
}
case LocalDeclContextKind::TopLevelCodeDecl:
return appendContext(local->getParent());
return appendContext(local->getParent(), useModuleName);
}
}

Expand All @@ -1663,7 +1663,7 @@ void ASTMangler::appendContext(const DeclContext *ctx) {
auto decl = ExtD->getExtendedNominal();
// Recover from erroneous extension.
if (!decl)
return appendContext(ExtD->getDeclContext());
return appendContext(ExtD->getDeclContext(), useModuleName);

if (!ExtD->isEquivalentToExtendedContext()) {
// Mangle the extension if:
Expand All @@ -1679,7 +1679,7 @@ void ASTMangler::appendContext(const DeclContext *ctx) {
// If the extension is constrained, mangle the generic signature that
// constrains it.
appendAnyGenericType(decl);
appendModule(ExtD->getParentModule());
appendModule(ExtD->getParentModule(), useModuleName);
if (sig && ExtD->isConstrainedExtension()) {
Mod = ExtD->getModuleContext();
auto nominalSig = ExtD->getSelfNominalTypeDecl()
Expand Down Expand Up @@ -1733,7 +1733,7 @@ void ASTMangler::appendContext(const DeclContext *ctx) {
} else {
// This is incorrect in that it does not produce a /unique/ mangling,
// but it will at least produce a /valid/ mangling.
appendContext(ctx->getParent());
appendContext(ctx->getParent(), useModuleName);
}
return;
}
Expand All @@ -1742,26 +1742,35 @@ void ASTMangler::appendContext(const DeclContext *ctx) {

case DeclContextKind::TopLevelCodeDecl:
// Mangle the containing module context.
return appendContext(ctx->getParent());
return appendContext(ctx->getParent(), useModuleName);
}

llvm_unreachable("bad decl context");
}

void ASTMangler::appendModule(const ModuleDecl *module) {
void ASTMangler::appendModule(const ModuleDecl *module,
StringRef useModuleName) {
assert(!module->getParent() && "cannot mangle nested modules!");

// Try the special 'swift' substitution.
if (module->isStdlibModule())
if (module->isStdlibModule()) {
assert(useModuleName.empty());
return appendOperator("s");
}

StringRef ModName = module->getName().str();
if (ModName == MANGLING_MODULE_OBJC)
if (ModName == MANGLING_MODULE_OBJC) {
assert(useModuleName.empty());
return appendOperator("So");
if (ModName == MANGLING_MODULE_CLANG_IMPORTER)
}
if (ModName == MANGLING_MODULE_CLANG_IMPORTER) {
assert(useModuleName.empty());
return appendOperator("SC");

appendIdentifier(ModName);
}
if (!useModuleName.empty())
appendIdentifier(useModuleName);
else
appendIdentifier(ModName);
}

/// Mangle the name of a protocol as a substitution candidate.
Expand Down Expand Up @@ -2327,7 +2336,7 @@ void ASTMangler::appendClosureComponents(Type Ty, unsigned discriminator,
assert(discriminator != AbstractClosureExpr::InvalidDiscriminator
&& "closure must be marked correctly with discriminator");

appendContext(parentContext);
appendContext(parentContext, StringRef());

if (!Ty)
Ty = ErrorType::get(parentContext->getASTContext());
Expand All @@ -2339,7 +2348,7 @@ void ASTMangler::appendClosureComponents(Type Ty, unsigned discriminator,

void ASTMangler::appendDefaultArgumentEntity(const DeclContext *func,
unsigned index) {
appendContext(func);
appendContext(func, StringRef());
appendOperator("fA", Index(index));
}

Expand Down Expand Up @@ -2542,8 +2551,11 @@ ASTMangler::appendProtocolConformance(const ProtocolConformance *conformance) {
needsModule = false;
}
}
if (needsModule)
appendModule(Mod);
if (needsModule) {
auto *DC = conformance->getDeclContext();
assert(DC->getAsDecl());
appendModule(Mod, DC->getAsDecl()->getAlternateModuleName());
}

contextSig =
conformingType->getAnyNominal()->getGenericSignatureOfContext();
Expand All @@ -2565,7 +2577,10 @@ void ASTMangler::appendProtocolConformanceRef(
// Same as "conformance module matches type", below.
appendOperator("HP");
} else if (isRetroactiveConformance(conformance)) {
appendModule(conformance->getDeclContext()->getParentModule());
auto *DC = conformance->getDeclContext();
assert(DC->getAsDecl());
appendModule(conformance->getDeclContext()->getParentModule(),
DC->getAsDecl()->getAlternateModuleName());
} else if (conformance->getDeclContext()->getParentModule() ==
conformance->getType()->getAnyNominal()->getParentModule()) {
appendOperator("HP");
Expand Down
16 changes: 16 additions & 0 deletions lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,22 @@ Result->X = SM.getLocFromExternalSource(Locs->SourceFilePath, Locs->X.Line, \
return Result;
}

StringRef Decl::getAlternateModuleName() const {
if (auto *OD = Attrs.getAttribute(DeclAttrKind::DAK_OriginallyDefinedIn)) {
return static_cast<const OriginallyDefinedInAttr*>(OD)->OriginalModuleName;
}
for (auto *DC = getDeclContext(); DC; DC = DC->getParent()) {
if (auto decl = DC->getAsDecl()) {
if (decl == this)
continue;
auto AM = decl->getAlternateModuleName();
if (!AM.empty())
return AM;
}
}
return StringRef();
}

SourceLoc Decl::getLoc(bool SerializedOK) const {
#define DECL(ID, X) \
static_assert(sizeof(checkSourceLocType(&ID##Decl::getLoc)) == 2, \
Expand Down
2 changes: 1 addition & 1 deletion lib/IRGen/IRGenMangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ mangleSymbolNameForSymbolicMangling(const SymbolicMangling &mangling,
= '_';
Buffer << ' ';
if (auto ty = referent.dyn_cast<const NominalTypeDecl*>())
appendContext(ty);
appendContext(ty, ty->getAlternateModuleName());
else if (auto opaque = referent.dyn_cast<const OpaqueTypeDecl*>())
appendOpaqueDeclName(opaque);
else
Expand Down
12 changes: 3 additions & 9 deletions lib/IRGen/IRGenMangler.h
Original file line number Diff line number Diff line change
Expand Up @@ -191,21 +191,21 @@ class IRGenMangler : public Mangle::ASTMangler {

std::string mangleModuleDescriptor(const ModuleDecl *Decl) {
beginMangling();
appendContext(Decl);
appendContext(Decl, Decl->getAlternateModuleName());
appendOperator("MXM");
return finalize();
}

std::string mangleExtensionDescriptor(const ExtensionDecl *Decl) {
beginMangling();
appendContext(Decl);
appendContext(Decl, Decl->getAlternateModuleName());
appendOperator("MXE");
return finalize();
}

void appendAnonymousDescriptorName(PointerUnion<DeclContext*, VarDecl*> Name){
if (auto DC = Name.dyn_cast<DeclContext *>()) {
return appendContext(DC);
return appendContext(DC, StringRef());
}
if (auto VD = Name.dyn_cast<VarDecl *>()) {
return appendEntity(VD);
Expand All @@ -228,12 +228,6 @@ class IRGenMangler : public Mangle::ASTMangler {
return finalize();
}

std::string mangleContext(const DeclContext *DC) {
beginMangling();
appendContext(DC);
return finalize();
}

std::string mangleBareProtocol(const ProtocolDecl *Decl) {
beginMangling();
appendAnyGenericType(Decl);
Expand Down
68 changes: 68 additions & 0 deletions test/IRGen/original-defined-attr.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// RUN: %target-swift-frontend -swift-version 4 -enforce-exclusivity=checked %s -emit-ir -module-name CurrentModule -D CURRENT_MODULE | %FileCheck %s --check-prefix=CHECK-COMMON --check-prefix=CHECK-CURRENT
// RUN: %target-swift-frontend -swift-version 4 -enforce-exclusivity=checked %s -emit-ir -module-name OriginalModule | %FileCheck %s --check-prefix=CHECK-COMMON --check-prefix=CHECK-ORIGINAL

#if CURRENT_MODULE

@_originallyDefinedIn(module: "OriginalModule", macOS 10.15)
public struct Entity {
public func addEntity(_ e: Entity) {}
public func removeEntity(_ e: Entity) {}
}

@_originallyDefinedIn(module: "OriginalModule", macOS 10.15)
public protocol Movable {
func MovableFuncFoo()
}

public protocol Unmoveable {}

@_originallyDefinedIn(module: "OriginalModule", macOS 10.15)
public class MovedClass: Movable, Unmoveable {
public func MovableFuncFoo() {}
}

public class UnmovableClass {}

#else

public struct Entity {
public func addEntity(_ e: Entity) {}
public func removeEntity(_ e: Entity) {}
}

public protocol Movable {
func MovableFuncFoo()
}

public protocol Unmoveable {}

public class MovedClass: Movable, Unmoveable {
public func MovableFuncFoo() {}
}

public class UnmovableClass {}

#endif


func entityClient() {
let root = Entity()
// CHECK-COMMON: call swiftcc void @"$s14OriginalModule6EntityVACycfC"()
let leaf = Entity()
// CHECK-COMMON: call swiftcc void @"$s14OriginalModule6EntityVACycfC"()
root.addEntity(leaf)
// CHECK-COMMON: call swiftcc void @"$s14OriginalModule6EntityV03addC0yyACF"()
let moved = MovedClass()
// CHECK-COMMON: call swiftcc %T14OriginalModule10MovedClassC* @"$s14OriginalModule10MovedClassCACycfC"
moved.MovableFuncFoo()
// CHECK-COMMON: call swiftcc void @"$s14OriginalModule10MovedClassC14MovableFuncFooyyF"
}

public func unmovableClient() {
let unmovable = UnmovableClass()
// CHECK-CURRENT: call swiftcc %swift.metadata_response @"$s13CurrentModule14UnmovableClassCMa"(i64 0)
// CHECK-ORIGINAL: call swiftcc %swift.metadata_response @"$s14OriginalModule14UnmovableClassCMa"(i64 0)
}

entityClient()
unmovableClient()