From 547f1547934404ac6e62692571bf61df14786984 Mon Sep 17 00:00:00 2001 From: Edd Barrett Date: Thu, 20 Apr 2023 09:44:37 +0100 Subject: [PATCH] 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. --- llvm/include/llvm/Transforms/Yk/Linkage.h | 10 ++++ llvm/lib/CodeGen/TargetPassConfig.cpp | 9 ++++ llvm/lib/Transforms/Yk/CMakeLists.txt | 1 + llvm/lib/Transforms/Yk/Linkage.cpp | 56 ++++++++++++++++++++ llvm/test/Transforms/Yk/Linkage/YkLinkage.ll | 10 ++++ 5 files changed, 86 insertions(+) create mode 100644 llvm/include/llvm/Transforms/Yk/Linkage.h create mode 100644 llvm/lib/Transforms/Yk/Linkage.cpp create mode 100644 llvm/test/Transforms/Yk/Linkage/YkLinkage.ll diff --git a/llvm/include/llvm/Transforms/Yk/Linkage.h b/llvm/include/llvm/Transforms/Yk/Linkage.h new file mode 100644 index 00000000000000..0a30a5f773dd92 --- /dev/null +++ b/llvm/include/llvm/Transforms/Yk/Linkage.h @@ -0,0 +1,10 @@ +#ifndef LLVM_TRANSFORMS_YK_LINKAGE_H +#define LLVM_TRANSFORMS_YK_LINKAGE_H + +#include "llvm/Pass.h" + +namespace llvm { +ModulePass *createYkLinkagePass(); +} // namespace llvm + +#endif diff --git a/llvm/lib/CodeGen/TargetPassConfig.cpp b/llvm/lib/CodeGen/TargetPassConfig.cpp index 1551032ab81ed4..d8726e9ba17189 100644 --- a/llvm/lib/CodeGen/TargetPassConfig.cpp +++ b/llvm/lib/CodeGen/TargetPassConfig.cpp @@ -48,6 +48,7 @@ #include "llvm/Transforms/Utils.h" #include "llvm/Transforms/Yk/BlockDisambiguate.h" #include "llvm/Transforms/Yk/ControlPoint.h" +#include "llvm/Transforms/Yk/Linkage.h" #include "llvm/Transforms/Yk/ShadowStack.h" #include "llvm/Transforms/Yk/Stackmaps.h" #include @@ -263,6 +264,10 @@ static cl::opt YkPatchCtrlPoint("yk-patch-control-point", cl::init(false), cl::NotHidden, cl::desc("Patch yk_mt_control_point()")); +static cl::opt YkLinkage("yk-linkage", cl::init(false), + cl::NotHidden, + cl::desc("Change functions with internal linkage to have external linkage")); + static cl::opt YkShadowStack("yk-shadow-stack", cl::init(false), cl::NotHidden, cl::desc("Use a shadow stack for stack values.")); @@ -1130,6 +1135,10 @@ bool TargetPassConfig::addISelPasses() { addPass(createYkControlPointPass()); } + if (YkLinkage) { + addPass(createYkLinkagePass()); + } + if (YkInsertStackMaps) { addPass(createYkStackmapsPass()); } diff --git a/llvm/lib/Transforms/Yk/CMakeLists.txt b/llvm/lib/Transforms/Yk/CMakeLists.txt index d8d8d71f0be6c6..075376a7bdd46c 100644 --- a/llvm/lib/Transforms/Yk/CMakeLists.txt +++ b/llvm/lib/Transforms/Yk/CMakeLists.txt @@ -1,6 +1,7 @@ add_llvm_component_library(LLVMYkPasses BlockDisambiguate.cpp ControlPoint.cpp + Linkage.cpp LivenessAnalysis.cpp StackMaps.cpp ShadowStack.cpp diff --git a/llvm/lib/Transforms/Yk/Linkage.cpp b/llvm/lib/Transforms/Yk/Linkage.cpp new file mode 100644 index 00000000000000..a31b6fcc16a355 --- /dev/null +++ b/llvm/lib/Transforms/Yk/Linkage.cpp @@ -0,0 +1,56 @@ +//===- Linkage.cpp - Ajdust linkage for the Yk JIT -----------------===// +// +// 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. + +#include "llvm/Transforms/Yk/Linkage.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Module.h" +#include "llvm/InitializePasses.h" +#include "llvm/Pass.h" + +#define DEBUG_TYPE "yk-linkage" + +using namespace llvm; + +namespace llvm { +void initializeYkLinkagePass(PassRegistry &); +} // namespace llvm + +namespace { +class YkLinkage : public ModulePass { +public: + static char ID; + YkLinkage() : ModulePass(ID) { + initializeYkLinkagePass(*PassRegistry::getPassRegistry()); + } + + bool runOnModule(Module &M) override { + for (Function &F : M) { + if (F.hasInternalLinkage()) { + F.setLinkage(GlobalVariable::ExternalLinkage); + } + } + return true; + } +}; +} // namespace + +char YkLinkage::ID = 0; +INITIALIZE_PASS(YkLinkage, DEBUG_TYPE, "yk-linkage", false, false) + +ModulePass *llvm::createYkLinkagePass() { return new YkLinkage(); } diff --git a/llvm/test/Transforms/Yk/Linkage/YkLinkage.ll b/llvm/test/Transforms/Yk/Linkage/YkLinkage.ll new file mode 100644 index 00000000000000..6537bd5d0b701d --- /dev/null +++ b/llvm/test/Transforms/Yk/Linkage/YkLinkage.ll @@ -0,0 +1,10 @@ +; Checks that the yk-linkage pass changes functions to have external linkage. +; +; RUN: llc --yk-linkage -o - < %s | FileCheck %s +; RUN: llc -o - < %s | FileCheck --check-prefix CHECK-NOPASS %s + +; CHECK: .globl myfunc +; CHECK-NOPASS-NOT: .globl myfunc +define internal void @myfunc() noinline { + ret void +}