1d245a8ae470e2ee84d138379f793095646c590e5Andrew Lenharth//===-- ExtractGV.cpp - Global Value extraction pass ----------------------===// 2d245a8ae470e2ee84d138379f793095646c590e5Andrew Lenharth// 3d245a8ae470e2ee84d138379f793095646c590e5Andrew Lenharth// The LLVM Compiler Infrastructure 4d245a8ae470e2ee84d138379f793095646c590e5Andrew Lenharth// 5d245a8ae470e2ee84d138379f793095646c590e5Andrew Lenharth// This file is distributed under the University of Illinois Open Source 6d245a8ae470e2ee84d138379f793095646c590e5Andrew Lenharth// License. See LICENSE.TXT for details. 7d245a8ae470e2ee84d138379f793095646c590e5Andrew Lenharth// 8d245a8ae470e2ee84d138379f793095646c590e5Andrew Lenharth//===----------------------------------------------------------------------===// 9d245a8ae470e2ee84d138379f793095646c590e5Andrew Lenharth// 10d245a8ae470e2ee84d138379f793095646c590e5Andrew Lenharth// This pass extracts global values 11d245a8ae470e2ee84d138379f793095646c590e5Andrew Lenharth// 12d245a8ae470e2ee84d138379f793095646c590e5Andrew Lenharth//===----------------------------------------------------------------------===// 13d245a8ae470e2ee84d138379f793095646c590e5Andrew Lenharth 14d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/Transforms/IPO.h" 15d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/ADT/SetVector.h" 160b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/Constants.h" 170b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/Instructions.h" 180b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/LLVMContext.h" 190b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/Module.h" 20d245a8ae470e2ee84d138379f793095646c590e5Andrew Lenharth#include "llvm/Pass.h" 2158d5e051574339106ce4139697ebadd21e34dbc0Ted Kremenek#include <algorithm> 22d245a8ae470e2ee84d138379f793095646c590e5Andrew Lenharthusing namespace llvm; 23d245a8ae470e2ee84d138379f793095646c590e5Andrew Lenharth 24d245a8ae470e2ee84d138379f793095646c590e5Andrew Lenharthnamespace { 25d245a8ae470e2ee84d138379f793095646c590e5Andrew Lenharth /// @brief A pass to extract specific functions and their dependencies. 266726b6d75a8b679068a58cb954ba97cf9d1690baNick Lewycky class GVExtractorPass : public ModulePass { 27b4e3cda1189fae8333fd3fa9051b47ed067ae1fdDan Gohman SetVector<GlobalValue *> Named; 28d245a8ae470e2ee84d138379f793095646c590e5Andrew Lenharth bool deleteStuff; 29d245a8ae470e2ee84d138379f793095646c590e5Andrew Lenharth public: 30d245a8ae470e2ee84d138379f793095646c590e5Andrew Lenharth static char ID; // Pass identification, replacement for typeid 31d245a8ae470e2ee84d138379f793095646c590e5Andrew Lenharth 32d245a8ae470e2ee84d138379f793095646c590e5Andrew Lenharth /// FunctionExtractorPass - If deleteFn is true, this pass deletes as the 33d245a8ae470e2ee84d138379f793095646c590e5Andrew Lenharth /// specified function. Otherwise, it deletes as much of the module as 34d245a8ae470e2ee84d138379f793095646c590e5Andrew Lenharth /// possible, except for the function specified. 35d245a8ae470e2ee84d138379f793095646c590e5Andrew Lenharth /// 36b4e3cda1189fae8333fd3fa9051b47ed067ae1fdDan Gohman explicit GVExtractorPass(std::vector<GlobalValue*>& GVs, bool deleteS = true) 37b4e3cda1189fae8333fd3fa9051b47ed067ae1fdDan Gohman : ModulePass(ID), Named(GVs.begin(), GVs.end()), deleteStuff(deleteS) {} 38d245a8ae470e2ee84d138379f793095646c590e5Andrew Lenharth 39d245a8ae470e2ee84d138379f793095646c590e5Andrew Lenharth bool runOnModule(Module &M) { 40b4e3cda1189fae8333fd3fa9051b47ed067ae1fdDan Gohman // Visit the global inline asm. 41b4e3cda1189fae8333fd3fa9051b47ed067ae1fdDan Gohman if (!deleteStuff) 42b4e3cda1189fae8333fd3fa9051b47ed067ae1fdDan Gohman M.setModuleInlineAsm(""); 43b4e3cda1189fae8333fd3fa9051b47ed067ae1fdDan Gohman 44b4e3cda1189fae8333fd3fa9051b47ed067ae1fdDan Gohman // For simplicity, just give all GlobalValues ExternalLinkage. A trickier 45b4e3cda1189fae8333fd3fa9051b47ed067ae1fdDan Gohman // implementation could figure out which GlobalValues are actually 46b4e3cda1189fae8333fd3fa9051b47ed067ae1fdDan Gohman // referenced by the Named set, and which GlobalValues in the rest of 47b4e3cda1189fae8333fd3fa9051b47ed067ae1fdDan Gohman // the module are referenced by the NamedSet, and get away with leaving 48b4e3cda1189fae8333fd3fa9051b47ed067ae1fdDan Gohman // more internal and private things internal and private. But for now, 49b4e3cda1189fae8333fd3fa9051b47ed067ae1fdDan Gohman // be conservative and simple. 50b4e3cda1189fae8333fd3fa9051b47ed067ae1fdDan Gohman 51b4e3cda1189fae8333fd3fa9051b47ed067ae1fdDan Gohman // Visit the GlobalVariables. 52b4e3cda1189fae8333fd3fa9051b47ed067ae1fdDan Gohman for (Module::global_iterator I = M.global_begin(), E = M.global_end(); 53edf017487ffdd52cd42f3129c0e6b78fffb31e89Bob Wilson I != E; ++I) { 549cb90e7c1578de19d00806cc121a8ef5ad6c9089Rafael Espindola bool Delete = 559cb90e7c1578de19d00806cc121a8ef5ad6c9089Rafael Espindola deleteStuff == (bool)Named.count(I) && !I->isDeclaration(); 569cb90e7c1578de19d00806cc121a8ef5ad6c9089Rafael Espindola if (!Delete) { 5756cb2298663017eb77aa4f4dda8db7ecd1b58173Bill Wendling if (I->hasAvailableExternallyLinkage()) 5856cb2298663017eb77aa4f4dda8db7ecd1b58173Bill Wendling continue; 5956cb2298663017eb77aa4f4dda8db7ecd1b58173Bill Wendling if (I->getName() == "llvm.global_ctors") 6056cb2298663017eb77aa4f4dda8db7ecd1b58173Bill Wendling continue; 6156cb2298663017eb77aa4f4dda8db7ecd1b58173Bill Wendling } 62d896d418510d16f47f8236f1956c3784e1520017Rafael Espindola 63880e8c0ad41345f353b819c51092baa8f05e1950Lang Hames bool Local = I->isDiscardableIfUnused(); 649cb90e7c1578de19d00806cc121a8ef5ad6c9089Rafael Espindola if (Local) 65edf017487ffdd52cd42f3129c0e6b78fffb31e89Bob Wilson I->setVisibility(GlobalValue::HiddenVisibility); 669cb90e7c1578de19d00806cc121a8ef5ad6c9089Rafael Espindola 679cb90e7c1578de19d00806cc121a8ef5ad6c9089Rafael Espindola if (Local || Delete) 689cb90e7c1578de19d00806cc121a8ef5ad6c9089Rafael Espindola I->setLinkage(GlobalValue::ExternalLinkage); 699cb90e7c1578de19d00806cc121a8ef5ad6c9089Rafael Espindola 709cb90e7c1578de19d00806cc121a8ef5ad6c9089Rafael Espindola if (Delete) 719cb90e7c1578de19d00806cc121a8ef5ad6c9089Rafael Espindola I->setInitializer(0); 72edf017487ffdd52cd42f3129c0e6b78fffb31e89Bob Wilson } 73b4e3cda1189fae8333fd3fa9051b47ed067ae1fdDan Gohman 74b4e3cda1189fae8333fd3fa9051b47ed067ae1fdDan Gohman // Visit the Functions. 75edf017487ffdd52cd42f3129c0e6b78fffb31e89Bob Wilson for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) { 769cb90e7c1578de19d00806cc121a8ef5ad6c9089Rafael Espindola bool Delete = 779cb90e7c1578de19d00806cc121a8ef5ad6c9089Rafael Espindola deleteStuff == (bool)Named.count(I) && !I->isDeclaration(); 789cb90e7c1578de19d00806cc121a8ef5ad6c9089Rafael Espindola if (!Delete) { 7956cb2298663017eb77aa4f4dda8db7ecd1b58173Bill Wendling if (I->hasAvailableExternallyLinkage()) 8056cb2298663017eb77aa4f4dda8db7ecd1b58173Bill Wendling continue; 8156cb2298663017eb77aa4f4dda8db7ecd1b58173Bill Wendling } 82d896d418510d16f47f8236f1956c3784e1520017Rafael Espindola 83880e8c0ad41345f353b819c51092baa8f05e1950Lang Hames bool Local = I->isDiscardableIfUnused(); 849cb90e7c1578de19d00806cc121a8ef5ad6c9089Rafael Espindola if (Local) 85edf017487ffdd52cd42f3129c0e6b78fffb31e89Bob Wilson I->setVisibility(GlobalValue::HiddenVisibility); 869cb90e7c1578de19d00806cc121a8ef5ad6c9089Rafael Espindola 879cb90e7c1578de19d00806cc121a8ef5ad6c9089Rafael Espindola if (Local || Delete) 889cb90e7c1578de19d00806cc121a8ef5ad6c9089Rafael Espindola I->setLinkage(GlobalValue::ExternalLinkage); 899cb90e7c1578de19d00806cc121a8ef5ad6c9089Rafael Espindola 909cb90e7c1578de19d00806cc121a8ef5ad6c9089Rafael Espindola if (Delete) 919cb90e7c1578de19d00806cc121a8ef5ad6c9089Rafael Espindola I->deleteBody(); 92edf017487ffdd52cd42f3129c0e6b78fffb31e89Bob Wilson } 93d245a8ae470e2ee84d138379f793095646c590e5Andrew Lenharth 94c0916d30e09192b7023e453aaa7d2ffe026345edRafael Espindola // Visit the Aliases. 95c0916d30e09192b7023e453aaa7d2ffe026345edRafael Espindola for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end(); 96c0916d30e09192b7023e453aaa7d2ffe026345edRafael Espindola I != E;) { 97c0916d30e09192b7023e453aaa7d2ffe026345edRafael Espindola Module::alias_iterator CurI = I; 98c0916d30e09192b7023e453aaa7d2ffe026345edRafael Espindola ++I; 99c0916d30e09192b7023e453aaa7d2ffe026345edRafael Espindola 100880e8c0ad41345f353b819c51092baa8f05e1950Lang Hames if (CurI->isDiscardableIfUnused()) { 101c0916d30e09192b7023e453aaa7d2ffe026345edRafael Espindola CurI->setVisibility(GlobalValue::HiddenVisibility); 1029cb90e7c1578de19d00806cc121a8ef5ad6c9089Rafael Espindola CurI->setLinkage(GlobalValue::ExternalLinkage); 1039cb90e7c1578de19d00806cc121a8ef5ad6c9089Rafael Espindola } 104c0916d30e09192b7023e453aaa7d2ffe026345edRafael Espindola 105c0916d30e09192b7023e453aaa7d2ffe026345edRafael Espindola if (deleteStuff == (bool)Named.count(CurI)) { 106c0916d30e09192b7023e453aaa7d2ffe026345edRafael Espindola Type *Ty = CurI->getType()->getElementType(); 107c0916d30e09192b7023e453aaa7d2ffe026345edRafael Espindola 108c0916d30e09192b7023e453aaa7d2ffe026345edRafael Espindola CurI->removeFromParent(); 109c0916d30e09192b7023e453aaa7d2ffe026345edRafael Espindola llvm::Value *Declaration; 110c0916d30e09192b7023e453aaa7d2ffe026345edRafael Espindola if (FunctionType *FTy = dyn_cast<FunctionType>(Ty)) { 111c0916d30e09192b7023e453aaa7d2ffe026345edRafael Espindola Declaration = Function::Create(FTy, GlobalValue::ExternalLinkage, 112c0916d30e09192b7023e453aaa7d2ffe026345edRafael Espindola CurI->getName(), &M); 113c0916d30e09192b7023e453aaa7d2ffe026345edRafael Espindola 114c0916d30e09192b7023e453aaa7d2ffe026345edRafael Espindola } else { 115c0916d30e09192b7023e453aaa7d2ffe026345edRafael Espindola Declaration = 116c0916d30e09192b7023e453aaa7d2ffe026345edRafael Espindola new GlobalVariable(M, Ty, false, GlobalValue::ExternalLinkage, 117c0916d30e09192b7023e453aaa7d2ffe026345edRafael Espindola 0, CurI->getName()); 118c0916d30e09192b7023e453aaa7d2ffe026345edRafael Espindola 119c0916d30e09192b7023e453aaa7d2ffe026345edRafael Espindola } 120c0916d30e09192b7023e453aaa7d2ffe026345edRafael Espindola CurI->replaceAllUsesWith(Declaration); 121c0916d30e09192b7023e453aaa7d2ffe026345edRafael Espindola delete CurI; 122c0916d30e09192b7023e453aaa7d2ffe026345edRafael Espindola } 123c0916d30e09192b7023e453aaa7d2ffe026345edRafael Espindola } 124c0916d30e09192b7023e453aaa7d2ffe026345edRafael Espindola 125d245a8ae470e2ee84d138379f793095646c590e5Andrew Lenharth return true; 126d245a8ae470e2ee84d138379f793095646c590e5Andrew Lenharth } 127d245a8ae470e2ee84d138379f793095646c590e5Andrew Lenharth }; 128d245a8ae470e2ee84d138379f793095646c590e5Andrew Lenharth 129d245a8ae470e2ee84d138379f793095646c590e5Andrew Lenharth char GVExtractorPass::ID = 0; 130d245a8ae470e2ee84d138379f793095646c590e5Andrew Lenharth} 131d245a8ae470e2ee84d138379f793095646c590e5Andrew Lenharth 132d245a8ae470e2ee84d138379f793095646c590e5Andrew LenharthModulePass *llvm::createGVExtractionPass(std::vector<GlobalValue*>& GVs, 133b4e3cda1189fae8333fd3fa9051b47ed067ae1fdDan Gohman bool deleteFn) { 134b4e3cda1189fae8333fd3fa9051b47ed067ae1fdDan Gohman return new GVExtractorPass(GVs, deleteFn); 135d245a8ae470e2ee84d138379f793095646c590e5Andrew Lenharth} 136