Andrew Lenharth | d245a8a | 2008-03-07 19:51:57 +0000 | [diff] [blame] | 1 | //===-- ExtractGV.cpp - Global Value extraction pass ----------------------===// |
| 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file is distributed under the University of Illinois Open Source |
| 6 | // License. See LICENSE.TXT for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | // |
| 10 | // This pass extracts global values |
| 11 | // |
| 12 | //===----------------------------------------------------------------------===// |
| 13 | |
Chandler Carruth | d04a8d4 | 2012-12-03 16:50:05 +0000 | [diff] [blame] | 14 | #include "llvm/Transforms/IPO.h" |
| 15 | #include "llvm/ADT/SetVector.h" |
| 16 | #include "llvm/Constants.h" |
Andrew Lenharth | d245a8a | 2008-03-07 19:51:57 +0000 | [diff] [blame] | 17 | #include "llvm/Instructions.h" |
Owen Anderson | 14ce9ef | 2009-07-06 01:34:54 +0000 | [diff] [blame] | 18 | #include "llvm/LLVMContext.h" |
Andrew Lenharth | d245a8a | 2008-03-07 19:51:57 +0000 | [diff] [blame] | 19 | #include "llvm/Module.h" |
| 20 | #include "llvm/Pass.h" |
Ted Kremenek | 58d5e05 | 2008-03-09 18:32:50 +0000 | [diff] [blame] | 21 | #include <algorithm> |
Andrew Lenharth | d245a8a | 2008-03-07 19:51:57 +0000 | [diff] [blame] | 22 | using namespace llvm; |
| 23 | |
| 24 | namespace { |
| 25 | /// @brief A pass to extract specific functions and their dependencies. |
Nick Lewycky | 6726b6d | 2009-10-25 06:33:48 +0000 | [diff] [blame] | 26 | class GVExtractorPass : public ModulePass { |
Dan Gohman | b4e3cda | 2010-08-26 00:22:55 +0000 | [diff] [blame] | 27 | SetVector<GlobalValue *> Named; |
Andrew Lenharth | d245a8a | 2008-03-07 19:51:57 +0000 | [diff] [blame] | 28 | bool deleteStuff; |
Andrew Lenharth | d245a8a | 2008-03-07 19:51:57 +0000 | [diff] [blame] | 29 | public: |
| 30 | static char ID; // Pass identification, replacement for typeid |
| 31 | |
| 32 | /// FunctionExtractorPass - If deleteFn is true, this pass deletes as the |
| 33 | /// specified function. Otherwise, it deletes as much of the module as |
| 34 | /// possible, except for the function specified. |
| 35 | /// |
Dan Gohman | b4e3cda | 2010-08-26 00:22:55 +0000 | [diff] [blame] | 36 | explicit GVExtractorPass(std::vector<GlobalValue*>& GVs, bool deleteS = true) |
| 37 | : ModulePass(ID), Named(GVs.begin(), GVs.end()), deleteStuff(deleteS) {} |
Andrew Lenharth | d245a8a | 2008-03-07 19:51:57 +0000 | [diff] [blame] | 38 | |
| 39 | bool runOnModule(Module &M) { |
Dan Gohman | b4e3cda | 2010-08-26 00:22:55 +0000 | [diff] [blame] | 40 | // Visit the global inline asm. |
| 41 | if (!deleteStuff) |
| 42 | M.setModuleInlineAsm(""); |
Andrew Lenharth | d245a8a | 2008-03-07 19:51:57 +0000 | [diff] [blame] | 43 | |
Dan Gohman | b4e3cda | 2010-08-26 00:22:55 +0000 | [diff] [blame] | 44 | // For simplicity, just give all GlobalValues ExternalLinkage. A trickier |
| 45 | // implementation could figure out which GlobalValues are actually |
| 46 | // referenced by the Named set, and which GlobalValues in the rest of |
| 47 | // the module are referenced by the NamedSet, and get away with leaving |
| 48 | // more internal and private things internal and private. But for now, |
| 49 | // be conservative and simple. |
Andrew Lenharth | d245a8a | 2008-03-07 19:51:57 +0000 | [diff] [blame] | 50 | |
Dan Gohman | b4e3cda | 2010-08-26 00:22:55 +0000 | [diff] [blame] | 51 | // Visit the GlobalVariables. |
| 52 | for (Module::global_iterator I = M.global_begin(), E = M.global_end(); |
Bob Wilson | edf0174 | 2010-09-23 17:25:06 +0000 | [diff] [blame] | 53 | I != E; ++I) { |
Rafael Espindola | 9cb90e7 | 2012-10-29 01:59:03 +0000 | [diff] [blame] | 54 | bool Delete = |
| 55 | deleteStuff == (bool)Named.count(I) && !I->isDeclaration(); |
| 56 | if (!Delete) { |
Bill Wendling | 56cb229 | 2012-07-19 00:11:40 +0000 | [diff] [blame] | 57 | if (I->hasAvailableExternallyLinkage()) |
| 58 | continue; |
| 59 | if (I->getName() == "llvm.global_ctors") |
| 60 | continue; |
| 61 | } |
Rafael Espindola | d896d41 | 2011-06-09 14:38:09 +0000 | [diff] [blame] | 62 | |
Rafael Espindola | 9cb90e7 | 2012-10-29 01:59:03 +0000 | [diff] [blame] | 63 | bool Local = I->hasLocalLinkage(); |
| 64 | if (Local) |
Bob Wilson | edf0174 | 2010-09-23 17:25:06 +0000 | [diff] [blame] | 65 | I->setVisibility(GlobalValue::HiddenVisibility); |
Rafael Espindola | 9cb90e7 | 2012-10-29 01:59:03 +0000 | [diff] [blame] | 66 | |
| 67 | if (Local || Delete) |
| 68 | I->setLinkage(GlobalValue::ExternalLinkage); |
| 69 | |
| 70 | if (Delete) |
| 71 | I->setInitializer(0); |
Bob Wilson | edf0174 | 2010-09-23 17:25:06 +0000 | [diff] [blame] | 72 | } |
Dan Gohman | b4e3cda | 2010-08-26 00:22:55 +0000 | [diff] [blame] | 73 | |
| 74 | // Visit the Functions. |
Bob Wilson | edf0174 | 2010-09-23 17:25:06 +0000 | [diff] [blame] | 75 | for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) { |
Rafael Espindola | 9cb90e7 | 2012-10-29 01:59:03 +0000 | [diff] [blame] | 76 | bool Delete = |
| 77 | deleteStuff == (bool)Named.count(I) && !I->isDeclaration(); |
| 78 | if (!Delete) { |
Bill Wendling | 56cb229 | 2012-07-19 00:11:40 +0000 | [diff] [blame] | 79 | if (I->hasAvailableExternallyLinkage()) |
| 80 | continue; |
| 81 | } |
Rafael Espindola | d896d41 | 2011-06-09 14:38:09 +0000 | [diff] [blame] | 82 | |
Rafael Espindola | 9cb90e7 | 2012-10-29 01:59:03 +0000 | [diff] [blame] | 83 | bool Local = I->hasLocalLinkage(); |
| 84 | if (Local) |
Bob Wilson | edf0174 | 2010-09-23 17:25:06 +0000 | [diff] [blame] | 85 | I->setVisibility(GlobalValue::HiddenVisibility); |
Rafael Espindola | 9cb90e7 | 2012-10-29 01:59:03 +0000 | [diff] [blame] | 86 | |
| 87 | if (Local || Delete) |
| 88 | I->setLinkage(GlobalValue::ExternalLinkage); |
| 89 | |
| 90 | if (Delete) |
| 91 | I->deleteBody(); |
Bob Wilson | edf0174 | 2010-09-23 17:25:06 +0000 | [diff] [blame] | 92 | } |
Andrew Lenharth | d245a8a | 2008-03-07 19:51:57 +0000 | [diff] [blame] | 93 | |
Rafael Espindola | c0916d3 | 2012-10-29 00:27:55 +0000 | [diff] [blame] | 94 | // Visit the Aliases. |
| 95 | for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end(); |
| 96 | I != E;) { |
| 97 | Module::alias_iterator CurI = I; |
| 98 | ++I; |
| 99 | |
Rafael Espindola | 9cb90e7 | 2012-10-29 01:59:03 +0000 | [diff] [blame] | 100 | if (CurI->hasLocalLinkage()) { |
Rafael Espindola | c0916d3 | 2012-10-29 00:27:55 +0000 | [diff] [blame] | 101 | CurI->setVisibility(GlobalValue::HiddenVisibility); |
Rafael Espindola | 9cb90e7 | 2012-10-29 01:59:03 +0000 | [diff] [blame] | 102 | CurI->setLinkage(GlobalValue::ExternalLinkage); |
| 103 | } |
Rafael Espindola | c0916d3 | 2012-10-29 00:27:55 +0000 | [diff] [blame] | 104 | |
| 105 | if (deleteStuff == (bool)Named.count(CurI)) { |
| 106 | Type *Ty = CurI->getType()->getElementType(); |
| 107 | |
| 108 | CurI->removeFromParent(); |
| 109 | llvm::Value *Declaration; |
| 110 | if (FunctionType *FTy = dyn_cast<FunctionType>(Ty)) { |
| 111 | Declaration = Function::Create(FTy, GlobalValue::ExternalLinkage, |
| 112 | CurI->getName(), &M); |
| 113 | |
| 114 | } else { |
| 115 | Declaration = |
| 116 | new GlobalVariable(M, Ty, false, GlobalValue::ExternalLinkage, |
| 117 | 0, CurI->getName()); |
| 118 | |
| 119 | } |
| 120 | CurI->replaceAllUsesWith(Declaration); |
| 121 | delete CurI; |
| 122 | } |
| 123 | } |
| 124 | |
Andrew Lenharth | d245a8a | 2008-03-07 19:51:57 +0000 | [diff] [blame] | 125 | return true; |
| 126 | } |
| 127 | }; |
| 128 | |
| 129 | char GVExtractorPass::ID = 0; |
| 130 | } |
| 131 | |
| 132 | ModulePass *llvm::createGVExtractionPass(std::vector<GlobalValue*>& GVs, |
Dan Gohman | b4e3cda | 2010-08-26 00:22:55 +0000 | [diff] [blame] | 133 | bool deleteFn) { |
| 134 | return new GVExtractorPass(GVs, deleteFn); |
Andrew Lenharth | d245a8a | 2008-03-07 19:51:57 +0000 | [diff] [blame] | 135 | } |