Skip to content

Commit e69fa3b

Browse files
author
Harlan Haskins
authored
Merge pull request swiftlang#27746 from harlanhaskins/away-in-a-mangler
[TBDGen] Mangle symbols before putting them in the TBD
2 parents c849652 + c94b952 commit e69fa3b

File tree

5 files changed

+102
-6
lines changed

5 files changed

+102
-6
lines changed

lib/FrontendTool/TBD.cpp

Lines changed: 9 additions & 1 deletion
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

Lines changed: 14 additions & 3 deletions
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/Process.h"
3841
#include "llvm/Support/YAMLTraits.h"
@@ -53,10 +56,15 @@ static bool isGlobalOrStaticVar(VarDecl *VD) {
5356
}
5457

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

5866
if (StringSymbols && kind == SymbolKind::GlobalSymbol) {
59-
auto isNewValue = StringSymbols->insert(name).second;
67+
auto isNewValue = StringSymbols->insert(mangled).second;
6068
(void)isNewValue;
6169
assert(isNewValue && "symbol appears twice");
6270
}
@@ -648,7 +656,10 @@ static void enumeratePublicSymbolsAndWrite(ModuleDecl *M, FileUnit *singleFile,
648656
file.addArch(arch);
649657
file.setPlatform(getPlatformKind(target));
650658

651-
TBDGenVisitor visitor(file, arch, symbols, linkInfo, M, opts);
659+
auto *clang = static_cast<ClangImporter *>(ctx.getClangModuleLoader());
660+
TBDGenVisitor visitor(file, arch, symbols,
661+
clang->getTargetInfo().getDataLayout(),
662+
linkInfo, M, opts);
652663

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

lib/TBDGen/TBDGenVisitor.h

Lines changed: 8 additions & 2 deletions
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

Lines changed: 31 additions & 0 deletions
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

Lines changed: 40 additions & 0 deletions
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)