Index: lib/Transforms/NaCl/GlobalCleanup.cpp |
diff --git a/lib/Transforms/NaCl/GlobalCleanup.cpp b/lib/Transforms/NaCl/GlobalCleanup.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..d489fefc1dcb6c311e3febae63f12758817db874 |
--- /dev/null |
+++ b/lib/Transforms/NaCl/GlobalCleanup.cpp |
@@ -0,0 +1,120 @@ |
+//===- 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 " |
+ "(assumes all of the binary is linked statically)", |
+ 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; |
+ } |
+ case GlobalValue::WeakAnyLinkage: { |
+ GV->setLinkage(GlobalValue::InternalLinkage); |
+ 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); |
+ } |
+ |
+ for (Module::iterator I = M.begin(), E = M.end(); I != E; ) { |
+ Function *F = I++; |
+ Modified |= CleanUpLinkage(F); |
+ } |
+ 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 *llvm::createResolveAliasesPass() { |
+ return new ResolveAliases(); |
+} |