Skip to content

Commit 547f154

Browse files
committed
Add the yk-linkage llvm pass.
The JIT relies upon the use of `dlsym()` at runtime in order to lookup any given function from its virtual address. For this to work the symbols for all functions must be in the dynamic symbol table. `yk-config` already provides the `--export-dynamic` flag in order to ensure that all *externally visible* symbols make it in to the dynamic symbol table, but that's not enough: functions marked for internal linkage (e.g. `static` functions in C) will be missed. This pass walks the functions of a module and flips any with internal linkage to external linkage. Note that whilst symbols with internal linkage can have the same name and be distinct, this is not so for symbols with external linkage. That's OK for us because Yk requires the use of LTO, and the LTO module merger will have already mangled the names for us so that symbol clashes can't occur.
1 parent 6e9fe3e commit 547f154

File tree

5 files changed

+86
-0
lines changed

5 files changed

+86
-0
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#ifndef LLVM_TRANSFORMS_YK_LINKAGE_H
2+
#define LLVM_TRANSFORMS_YK_LINKAGE_H
3+
4+
#include "llvm/Pass.h"
5+
6+
namespace llvm {
7+
ModulePass *createYkLinkagePass();
8+
} // namespace llvm
9+
10+
#endif

llvm/lib/CodeGen/TargetPassConfig.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
#include "llvm/Transforms/Utils.h"
4949
#include "llvm/Transforms/Yk/BlockDisambiguate.h"
5050
#include "llvm/Transforms/Yk/ControlPoint.h"
51+
#include "llvm/Transforms/Yk/Linkage.h"
5152
#include "llvm/Transforms/Yk/ShadowStack.h"
5253
#include "llvm/Transforms/Yk/Stackmaps.h"
5354
#include <cassert>
@@ -263,6 +264,10 @@ static cl::opt<bool> YkPatchCtrlPoint("yk-patch-control-point", cl::init(false),
263264
cl::NotHidden,
264265
cl::desc("Patch yk_mt_control_point()"));
265266

267+
static cl::opt<bool> YkLinkage("yk-linkage", cl::init(false),
268+
cl::NotHidden,
269+
cl::desc("Change functions with internal linkage to have external linkage"));
270+
266271
static cl::opt<bool>
267272
YkShadowStack("yk-shadow-stack", cl::init(false), cl::NotHidden,
268273
cl::desc("Use a shadow stack for stack values."));
@@ -1130,6 +1135,10 @@ bool TargetPassConfig::addISelPasses() {
11301135
addPass(createYkControlPointPass());
11311136
}
11321137

1138+
if (YkLinkage) {
1139+
addPass(createYkLinkagePass());
1140+
}
1141+
11331142
if (YkInsertStackMaps) {
11341143
addPass(createYkStackmapsPass());
11351144
}

llvm/lib/Transforms/Yk/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
add_llvm_component_library(LLVMYkPasses
22
BlockDisambiguate.cpp
33
ControlPoint.cpp
4+
Linkage.cpp
45
LivenessAnalysis.cpp
56
StackMaps.cpp
67
ShadowStack.cpp

llvm/lib/Transforms/Yk/Linkage.cpp

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
//===- Linkage.cpp - Ajdust linkage for the Yk JIT -----------------===//
2+
//
3+
// The JIT relies upon the use of `dlsym()` at runtime in order to lookup any
4+
// given function from its virtual address. For this to work the symbols for
5+
// all functions must be in the dynamic symbol table.
6+
//
7+
// `yk-config` already provides the `--export-dynamic` flag in order to ensure
8+
// that all *externally visible* symbols make it in to the dynamic symbol table,
9+
// but that's not enough: functions marked for internal linkage (e.g. `static`
10+
// functions in C) will be missed.
11+
//
12+
// This pass walks the functions of a module and flips any with internal linkage
13+
// to external linkage.
14+
//
15+
// Note that whilst symbols with internal linkage can have the same name and be
16+
// distinct, this is not so for symbols with external linkage. That's OK for
17+
// us because Yk requires the use of LTO, and the LTO module merger will have
18+
// already mangled the names for us so that symbol clashes can't occur.
19+
20+
#include "llvm/Transforms/Yk/Linkage.h"
21+
#include "llvm/IR/Function.h"
22+
#include "llvm/IR/Module.h"
23+
#include "llvm/InitializePasses.h"
24+
#include "llvm/Pass.h"
25+
26+
#define DEBUG_TYPE "yk-linkage"
27+
28+
using namespace llvm;
29+
30+
namespace llvm {
31+
void initializeYkLinkagePass(PassRegistry &);
32+
} // namespace llvm
33+
34+
namespace {
35+
class YkLinkage : public ModulePass {
36+
public:
37+
static char ID;
38+
YkLinkage() : ModulePass(ID) {
39+
initializeYkLinkagePass(*PassRegistry::getPassRegistry());
40+
}
41+
42+
bool runOnModule(Module &M) override {
43+
for (Function &F : M) {
44+
if (F.hasInternalLinkage()) {
45+
F.setLinkage(GlobalVariable::ExternalLinkage);
46+
}
47+
}
48+
return true;
49+
}
50+
};
51+
} // namespace
52+
53+
char YkLinkage::ID = 0;
54+
INITIALIZE_PASS(YkLinkage, DEBUG_TYPE, "yk-linkage", false, false)
55+
56+
ModulePass *llvm::createYkLinkagePass() { return new YkLinkage(); }
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
; Checks that the yk-linkage pass changes functions to have external linkage.
2+
;
3+
; RUN: llc --yk-linkage -o - < %s | FileCheck %s
4+
; RUN: llc -o - < %s | FileCheck --check-prefix CHECK-NOPASS %s
5+
6+
; CHECK: .globl myfunc
7+
; CHECK-NOPASS-NOT: .globl myfunc
8+
define internal void @myfunc() noinline {
9+
ret void
10+
}

0 commit comments

Comments
 (0)