aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llvm/InitializePasses.h4
-rw-r--r--include/llvm/Transforms/NaCl.h2
-rw-r--r--lib/Transforms/NaCl/CMakeLists.txt1
-rw-r--r--lib/Transforms/NaCl/GlobalCleanup.cpp109
-rw-r--r--test/Transforms/NaCl/globalcleanup.ll34
-rw-r--r--test/Transforms/NaCl/resolve-aliases.ll36
-rw-r--r--tools/opt/opt.cpp4
7 files changed, 189 insertions, 1 deletions
diff --git a/include/llvm/InitializePasses.h b/include/llvm/InitializePasses.h
index 0655c22545..9934ff3a9a 100644
--- a/include/llvm/InitializePasses.h
+++ b/include/llvm/InitializePasses.h
@@ -279,12 +279,14 @@ void initializeMachineFunctionPrinterPassPass(PassRegistry&);
// @LOCALMOD-BEGIN
void initializeExpandConstantExprPass(PassRegistry&);
void initializeExpandCtorsPass(PassRegistry&);
-void initializeExpandTlsPass(PassRegistry&);
void initializeExpandTlsConstantExprPass(PassRegistry&);
+void initializeExpandTlsPass(PassRegistry&);
void initializeExpandVarArgsPass(PassRegistry&);
+void initializeGlobalCleanupPass(PassRegistry&);
void initializeNaClCcRewritePass(PassRegistry&);
void initializePNaClABIVerifyModulePass(PassRegistry&);
void initializePNaClABIVerifyFunctionsPass(PassRegistry&);
+void initializeResolveAliasesPass(PassRegistry&);
// @LOCALMOD-END
}
diff --git a/include/llvm/Transforms/NaCl.h b/include/llvm/Transforms/NaCl.h
index 6494200f6d..b5108fbf32 100644
--- a/include/llvm/Transforms/NaCl.h
+++ b/include/llvm/Transforms/NaCl.h
@@ -20,6 +20,8 @@ ModulePass *createExpandCtorsPass();
ModulePass *createExpandTlsPass();
ModulePass *createExpandTlsConstantExprPass();
ModulePass *createExpandVarArgsPass();
+ModulePass *createGlobalCleanupPass();
+ModulePass *createResolveAliasesPass();
}
diff --git a/lib/Transforms/NaCl/CMakeLists.txt b/lib/Transforms/NaCl/CMakeLists.txt
index 6ba9dcc68b..5b1de88dc4 100644
--- a/lib/Transforms/NaCl/CMakeLists.txt
+++ b/lib/Transforms/NaCl/CMakeLists.txt
@@ -4,6 +4,7 @@ add_llvm_library(LLVMTransformsNaCl
ExpandTls.cpp
ExpandTlsConstantExpr.cpp
ExpandVarArgs.cpp
+ GlobalCleanup.cpp
)
add_dependencies(LLVMTransformsNaCl intrinsics_gen)
diff --git a/lib/Transforms/NaCl/GlobalCleanup.cpp b/lib/Transforms/NaCl/GlobalCleanup.cpp
new file mode 100644
index 0000000000..9a28063af6
--- /dev/null
+++ b/lib/Transforms/NaCl/GlobalCleanup.cpp
@@ -0,0 +1,109 @@
+//===- GlobalCleanup.cpp - Cleanup global symbols post-bitcode-link -------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+// ===---------------------------------------------------------------------===//
+//
+// PNaCl executables should have no external symbols or aliases. These passes
+// internalize (or otherwise remove/resolve) GlobalValues and resolve all
+// GlobalAliases.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Pass.h"
+#include "llvm/Transforms/NaCl.h"
+
+using namespace llvm;
+
+namespace {
+ class GlobalCleanup : public ModulePass {
+ public:
+ static char ID;
+ GlobalCleanup() : ModulePass(ID) {
+ initializeGlobalCleanupPass(*PassRegistry::getPassRegistry());
+ }
+ virtual bool runOnModule(Module &M);
+ };
+
+ class ResolveAliases : public ModulePass {
+ public:
+ static char ID;
+ ResolveAliases() : ModulePass(ID) {
+ initializeResolveAliasesPass(*PassRegistry::getPassRegistry());
+ }
+ virtual bool runOnModule(Module &M);
+ };
+}
+
+char GlobalCleanup::ID = 0;
+INITIALIZE_PASS(GlobalCleanup, "nacl-global-cleanup",
+ "GlobalValue cleanup for PNaCl", false, false)
+
+static bool CleanUpLinkage(GlobalValue *GV) {
+ // TODO(dschuff): handle the rest of the linkage types as necessary without
+ // running afoul of the IR verifier or breaking the native link
+ switch (GV->getLinkage()) {
+ case GlobalValue::ExternalWeakLinkage: {
+ Constant *NullRef = Constant::getNullValue(GV->getType());
+ GV->replaceAllUsesWith(NullRef);
+ GV->eraseFromParent();
+ return true;
+ }
+ default:
+ // default with fall through to avoid compiler warning
+ return false;
+ }
+ return false;
+}
+
+bool GlobalCleanup::runOnModule(Module &M) {
+ bool Modified = false;
+
+ if (GlobalVariable *GV = M.getNamedGlobal("llvm.compiler.used")) {
+ GV->eraseFromParent();
+ Modified = true;
+ }
+ if (GlobalVariable *GV = M.getNamedGlobal("llvm.used")) {
+ GV->eraseFromParent();
+ Modified = true;
+ }
+
+ for (Module::global_iterator I = M.global_begin(), E = M.global_end();
+ I != E; ) {
+ GlobalVariable *GV = I++;
+ Modified |= CleanUpLinkage(GV);
+ }
+ return Modified;
+}
+
+ModulePass *llvm::createGlobalCleanupPass() {
+ return new GlobalCleanup();
+}
+
+char ResolveAliases::ID = 0;
+INITIALIZE_PASS(ResolveAliases, "resolve-aliases",
+ "resolve global variable and function aliases", false, false)
+
+bool ResolveAliases::runOnModule(Module &M) {
+ bool Modified = false;
+
+ for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end();
+ I != E; ) {
+ GlobalAlias *Alias = I++;
+ Alias->replaceAllUsesWith(Alias->getAliasee());
+ Alias->eraseFromParent();
+ Modified = true;
+ }
+ return Modified;
+}
+
+ModulePass *createResolveAliasesPass() {
+ return new ResolveAliases();
+}
diff --git a/test/Transforms/NaCl/globalcleanup.ll b/test/Transforms/NaCl/globalcleanup.ll
new file mode 100644
index 0000000000..3af5df003e
--- /dev/null
+++ b/test/Transforms/NaCl/globalcleanup.ll
@@ -0,0 +1,34 @@
+; RUN: opt < %s -nacl-global-cleanup -S | FileCheck %s
+; RUN: opt < %s -nacl-global-cleanup -S | FileCheck -check-prefix=GV %s
+
+@llvm.compiler.used = appending global [0 x i8*] zeroinitializer, section "llvm.metadata"
+@llvm.used = appending global [0 x i8*] zeroinitializer, section "llvm.metadata"
+
+; GV-NOT: llvm.used
+; GV-NOT: llvm.compiler.used
+
+@extern_weak_const = extern_weak constant i32
+@extern_weak_gv = extern_weak global i32
+
+; GV-NOT: @extern_weak_const
+; GV-NOT: @extern_weak_gv
+
+; CHECK define void @_start
+define void @_start() {
+ ret void
+}
+
+define i32* @ewgv() {
+; CHECK: %bc = getelementptr i8* null, i32 0
+ %bc = getelementptr i8* bitcast (i32* @extern_weak_gv to i8*), i32 0
+; CHECK: ret i32* null
+ ret i32* @extern_weak_gv
+}
+
+define i32* @ewc() {
+; CHECK: %bc = getelementptr i8* null, i32 0
+ %bc = getelementptr i8* bitcast (i32* @extern_weak_const to i8*), i32 0
+; CHECK: ret i32* null
+ ret i32* @extern_weak_gv
+}
+
diff --git a/test/Transforms/NaCl/resolve-aliases.ll b/test/Transforms/NaCl/resolve-aliases.ll
new file mode 100644
index 0000000000..82ad54d74e
--- /dev/null
+++ b/test/Transforms/NaCl/resolve-aliases.ll
@@ -0,0 +1,36 @@
+; RUN: opt < %s -resolve-aliases -S | FileCheck %s
+
+; CHECK-NOT: @alias
+
+@r1 = internal global i32 zeroinitializer
+@a1 = alias i32* @r1
+define i32* @usea1() {
+; CHECK: ret i32* @r1
+ ret i32* @a1
+}
+
+@funcalias = alias i32* ()* @usea1
+; CHECK: @usefuncalias
+define void @usefuncalias() {
+; CHECK: call i32* @usea1
+ %1 = call i32* @funcalias()
+ ret void
+}
+
+@bc1 = global i8* bitcast (i32* @r1 to i8*)
+@bcalias = alias i8* bitcast (i32* @r1 to i8*)
+
+; CHECK: @usebcalias
+define i8* @usebcalias() {
+; CHECK: ret i8* bitcast (i32* @r1 to i8*)
+ ret i8* @bcalias
+}
+
+
+@fa2 = alias i32* ()* @funcalias
+; CHECK: @usefa2
+define void @usefa2() {
+; CHECK: call i32* @usea1
+ call i32* @fa2()
+ ret void
+}
diff --git a/tools/opt/opt.cpp b/tools/opt/opt.cpp
index 04fa332266..337419553a 100644
--- a/tools/opt/opt.cpp
+++ b/tools/opt/opt.cpp
@@ -576,11 +576,15 @@ int main(int argc, char **argv) {
initializeInstCombine(Registry);
initializeInstrumentation(Registry);
initializeTarget(Registry);
+ // @LOCALMOD-BEGIN
initializeExpandConstantExprPass(Registry);
initializeExpandCtorsPass(Registry);
initializeExpandTlsPass(Registry);
initializeExpandTlsConstantExprPass(Registry);
initializeExpandVarArgsPass(Registry);
+ initializeGlobalCleanupPass(Registry);
+ initializeResolveAliasesPass(Registry);
+ // @LOCALMOD-END
cl::ParseCommandLineOptions(argc, argv,
"llvm .bc -> .bc modular optimizer and analysis printer\n");