Skip to content

Commit c94b952

Browse files
author
Harlan Haskins
committed
[TBDGen] Mangle symbols before putting them in the TBD
The linker expects to see mangled symbols in the TBD, otherwise it won't be able to link anything. Use LLVM's mangler to mangle them. Fixes rdar://54055049
1 parent ad8a611 commit c94b952

File tree

5 files changed

+102
-6
lines changed

5 files changed

+102
-6
lines changed

lib/FrontendTool/TBD.cpp

+9-1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "llvm/ADT/StringRef.h"
2626
#include "llvm/ADT/StringSet.h"
2727
#include "llvm/IR/Module.h"
28+
#include "llvm/IR/Mangler.h"
2829
#include "llvm/IR/ValueSymbolTable.h"
2930
#include "llvm/Support/FileSystem.h"
3031
#include <vector>
@@ -85,7 +86,14 @@ static bool validateSymbolSet(DiagnosticEngine &diags,
8586
std::vector<StringRef> irNotTBD;
8687

8788
for (auto &nameValue : IRModule.getValueSymbolTable()) {
88-
auto name = nameValue.getKey();
89+
// TBDGen inserts mangled names (usually with a leading '_') into its
90+
// symbol table, so make sure to mangle IRGen names before comparing them
91+
// with what TBDGen created.
92+
auto unmangledName = nameValue.getKey();
93+
SmallString<128> name;
94+
llvm::Mangler::getNameWithPrefix(name, unmangledName,
95+
IRModule.getDataLayout());
96+
8997
auto value = nameValue.getValue();
9098
if (auto GV = dyn_cast<llvm::GlobalValue>(value)) {
9199
// Is this a symbol that should be listed?

lib/TBDGen/TBDGen.cpp

+14-3
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "swift/AST/ParameterList.h"
2424
#include "swift/AST/PropertyWrappers.h"
2525
#include "swift/Basic/LLVM.h"
26+
#include "swift/ClangImporter/ClangImporter.h"
2627
#include "swift/IRGen/IRGenPublic.h"
2728
#include "swift/IRGen/Linking.h"
2829
#include "swift/SIL/FormalLinkage.h"
@@ -32,7 +33,9 @@
3233
#include "swift/SIL/SILWitnessTable.h"
3334
#include "swift/SIL/SILWitnessVisitor.h"
3435
#include "swift/SIL/TypeLowering.h"
36+
#include "clang/Basic/TargetInfo.h"
3537
#include "llvm/ADT/StringSet.h"
38+
#include "llvm/IR/Mangler.h"
3639
#include "llvm/Support/Error.h"
3740
#include "llvm/Support/YAMLTraits.h"
3841
#include "llvm/TextAPI/MachO/InterfaceFile.h"
@@ -52,10 +55,15 @@ static bool isGlobalOrStaticVar(VarDecl *VD) {
5255
}
5356

5457
void TBDGenVisitor::addSymbol(StringRef name, SymbolKind kind) {
55-
Symbols.addSymbol(kind, name, Archs);
58+
// The linker expects to see mangled symbol names in TBD files, so make sure
59+
// to mangle before inserting the symbol.
60+
SmallString<32> mangled;
61+
llvm::Mangler::getNameWithPrefix(mangled, name, DataLayout);
62+
63+
Symbols.addSymbol(kind, mangled, Archs);
5664

5765
if (StringSymbols && kind == SymbolKind::GlobalSymbol) {
58-
auto isNewValue = StringSymbols->insert(name).second;
66+
auto isNewValue = StringSymbols->insert(mangled).second;
5967
(void)isNewValue;
6068
assert(isNewValue && "symbol appears twice");
6169
}
@@ -640,7 +648,10 @@ static void enumeratePublicSymbolsAndWrite(ModuleDecl *M, FileUnit *singleFile,
640648
file.addArch(arch);
641649
file.setPlatform(getPlatformKind(target));
642650

643-
TBDGenVisitor visitor(file, arch, symbols, linkInfo, M, opts);
651+
auto *clang = static_cast<ClangImporter *>(ctx.getClangModuleLoader());
652+
TBDGenVisitor visitor(file, arch, symbols,
653+
clang->getTargetInfo().getDataLayout(),
654+
linkInfo, M, opts);
644655

645656
auto visitFile = [&](FileUnit *file) {
646657
if (file == M->getFiles()[0]) {

lib/TBDGen/TBDGenVisitor.h

+8-2
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@
3434
using namespace swift::irgen;
3535
using StringSet = llvm::StringSet<>;
3636

37+
namespace llvm {
38+
class DataLayout;
39+
}
40+
3741
namespace swift {
3842

3943
struct TBDGenOptions;
@@ -45,6 +49,7 @@ class TBDGenVisitor : public ASTVisitor<TBDGenVisitor> {
4549
llvm::MachO::InterfaceFile &Symbols;
4650
llvm::MachO::ArchitectureSet Archs;
4751
StringSet *StringSymbols;
52+
const llvm::DataLayout &DataLayout;
4853

4954
const UniversalLinkageInfo &UniversalLinkInfo;
5055
ModuleDecl *SwiftModule;
@@ -72,11 +77,12 @@ class TBDGenVisitor : public ASTVisitor<TBDGenVisitor> {
7277
public:
7378
TBDGenVisitor(llvm::MachO::InterfaceFile &symbols,
7479
llvm::MachO::ArchitectureSet archs, StringSet *stringSymbols,
80+
const llvm::DataLayout &dataLayout,
7581
const UniversalLinkageInfo &universalLinkInfo,
7682
ModuleDecl *swiftModule, const TBDGenOptions &opts)
7783
: Symbols(symbols), Archs(archs), StringSymbols(stringSymbols),
78-
UniversalLinkInfo(universalLinkInfo), SwiftModule(swiftModule),
79-
Opts(opts) {}
84+
DataLayout(dataLayout), UniversalLinkInfo(universalLinkInfo),
85+
SwiftModule(swiftModule), Opts(opts) {}
8086

8187
void addMainIfNecessary(FileUnit *file) {
8288
// HACK: 'main' is a special symbol that's always emitted in SILGen if

test/TBD/Inputs/api_grab_bag.swift

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
public class PublicClass {
2+
public func method() {
3+
}
4+
5+
public init() {
6+
}
7+
}
8+
9+
public class PublicSubclass: PublicClass {
10+
public override func method() {
11+
}
12+
}
13+
14+
public protocol PublicProtocol {
15+
var publicStruct: PublicStruct { get }
16+
}
17+
18+
public struct PublicStruct {
19+
public init() {}
20+
}
21+
22+
extension PublicStruct: PublicProtocol {
23+
public var publicStruct: PublicStruct { return self }
24+
}
25+
26+
public enum PublicEnum: PublicProtocol {
27+
case caseOne
28+
case caseTwo
29+
30+
public var publicStruct: PublicStruct { return PublicStruct() }
31+
}

test/TBD/linking-with-tbd.swift

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// REQUIRES: VENDOR=apple
2+
3+
// 1. Create a skeleton of a framework
4+
// RUN: %empty-directory(%t/APIGrabBag.framework/Modules/APIGrabBag.swiftmodule)
5+
// RUN: %empty-directory(%t/APIGrabBag.framework/Headers)
6+
7+
// 1. Compile api_grab_bag.swift to a .tbd and put it in %t
8+
9+
// RUN: %target-swift-frontend -emit-module -o %t/APIGrabBag.framework/Modules/APIGrabBag.swiftmodule/%target-cpu.swiftmodule -emit-tbd-path %t/APIGrabBag.framework/APIGrabBag.tbd %S/Inputs/api_grab_bag.swift -module-name APIGrabBag -tbd-install_name %t/APIGrabBag.framework/APIGrabBag
10+
11+
// 2. Compile the current file against the TBD
12+
13+
// RUN: %target-build-swift -emit-executable %s -o %t/executable -F %t -framework APIGrabBag
14+
15+
// 3. Install the actual dylib into the framework
16+
17+
// RUN: %target-build-swift -emit-library %S/Inputs/api_grab_bag.swift -module-name APIGrabBag -o %t/APIGrabBag.framework/APIGrabBag
18+
19+
// 4. Codesign the executable and run it
20+
21+
// RUN: %target-codesign %t/executable %t/APIGrabBag.framework/APIGrabBag
22+
// RUN: %target-run %t/executable
23+
24+
import APIGrabBag
25+
26+
func useAPIs() {
27+
let c = PublicClass()
28+
c.method()
29+
30+
let sub = PublicSubclass()
31+
sub.method()
32+
33+
let s = PublicStruct()
34+
let t = s.publicStruct
35+
36+
var e = PublicEnum.caseOne
37+
e = .caseTwo
38+
39+
_ = e.publicStruct
40+
}

0 commit comments

Comments
 (0)