blob: 3f313b11cab207eac3d07d8c8f60367651c9c4f6 [file] [log] [blame] [edit]
//===- 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/ADT/Triple.h"
#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());
}
bool runOnModule(Module &M) override;
};
class ResolveAliases : public ModulePass {
public:
static char ID;
ResolveAliases() : ModulePass(ID) {
initializeResolveAliasesPass(*PassRegistry::getPassRegistry());
}
bool runOnModule(Module &M) override;
};
}
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: {
auto *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;
// Cleanup llvm.compiler.used. We leave llvm.used as-is,
// because optimization passes feed off it to understand
// what globals may/may not be optimized away. For PNaCl,
// it is removed before ABI validation by CleanupUsedGlobalsMetadata.
if (auto *GV = M.getNamedGlobal("llvm.compiler.used")) {
GV->eraseFromParent();
Modified = true;
}
for (auto I = M.global_begin(), E = M.global_end(); I != E;) {
GlobalVariable *GV = I++;
Modified |= CleanUpLinkage(GV);
}
for (auto 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 (auto 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(); }