]>
Commit | Line | Data |
---|---|---|
223e47cc LB |
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 | ||
223e47cc LB |
14 | #include "llvm/Transforms/IPO.h" |
15 | #include "llvm/ADT/SetVector.h" | |
970d7e83 LB |
16 | #include "llvm/IR/Constants.h" |
17 | #include "llvm/IR/Instructions.h" | |
18 | #include "llvm/IR/LLVMContext.h" | |
19 | #include "llvm/IR/Module.h" | |
20 | #include "llvm/Pass.h" | |
223e47cc LB |
21 | #include <algorithm> |
22 | using namespace llvm; | |
23 | ||
1a4d82fc JJ |
24 | /// Make sure GV is visible from both modules. Delete is true if it is |
25 | /// being deleted from this module. | |
26 | /// This also makes sure GV cannot be dropped so that references from | |
27 | /// the split module remain valid. | |
28 | static void makeVisible(GlobalValue &GV, bool Delete) { | |
29 | bool Local = GV.hasLocalLinkage(); | |
30 | if (Local || Delete) { | |
31 | GV.setLinkage(GlobalValue::ExternalLinkage); | |
32 | if (Local) | |
33 | GV.setVisibility(GlobalValue::HiddenVisibility); | |
34 | return; | |
35 | } | |
36 | ||
37 | if (!GV.hasLinkOnceLinkage()) { | |
38 | assert(!GV.isDiscardableIfUnused()); | |
39 | return; | |
40 | } | |
41 | ||
42 | // Map linkonce* to weak* so that llvm doesn't drop this GV. | |
43 | switch(GV.getLinkage()) { | |
44 | default: | |
45 | llvm_unreachable("Unexpected linkage"); | |
46 | case GlobalValue::LinkOnceAnyLinkage: | |
47 | GV.setLinkage(GlobalValue::WeakAnyLinkage); | |
48 | return; | |
49 | case GlobalValue::LinkOnceODRLinkage: | |
50 | GV.setLinkage(GlobalValue::WeakODRLinkage); | |
51 | return; | |
52 | } | |
53 | } | |
54 | ||
223e47cc LB |
55 | namespace { |
56 | /// @brief A pass to extract specific functions and their dependencies. | |
57 | class GVExtractorPass : public ModulePass { | |
58 | SetVector<GlobalValue *> Named; | |
59 | bool deleteStuff; | |
60 | public: | |
61 | static char ID; // Pass identification, replacement for typeid | |
62 | ||
63 | /// FunctionExtractorPass - If deleteFn is true, this pass deletes as the | |
64 | /// specified function. Otherwise, it deletes as much of the module as | |
65 | /// possible, except for the function specified. | |
66 | /// | |
67 | explicit GVExtractorPass(std::vector<GlobalValue*>& GVs, bool deleteS = true) | |
68 | : ModulePass(ID), Named(GVs.begin(), GVs.end()), deleteStuff(deleteS) {} | |
69 | ||
1a4d82fc | 70 | bool runOnModule(Module &M) override { |
223e47cc LB |
71 | // Visit the global inline asm. |
72 | if (!deleteStuff) | |
73 | M.setModuleInlineAsm(""); | |
74 | ||
75 | // For simplicity, just give all GlobalValues ExternalLinkage. A trickier | |
76 | // implementation could figure out which GlobalValues are actually | |
77 | // referenced by the Named set, and which GlobalValues in the rest of | |
78 | // the module are referenced by the NamedSet, and get away with leaving | |
79 | // more internal and private things internal and private. But for now, | |
80 | // be conservative and simple. | |
81 | ||
82 | // Visit the GlobalVariables. | |
83 | for (Module::global_iterator I = M.global_begin(), E = M.global_end(); | |
84 | I != E; ++I) { | |
970d7e83 LB |
85 | bool Delete = |
86 | deleteStuff == (bool)Named.count(I) && !I->isDeclaration(); | |
87 | if (!Delete) { | |
223e47cc LB |
88 | if (I->hasAvailableExternallyLinkage()) |
89 | continue; | |
90 | if (I->getName() == "llvm.global_ctors") | |
91 | continue; | |
92 | } | |
93 | ||
85aaf69f | 94 | makeVisible(*I, Delete); |
970d7e83 LB |
95 | |
96 | if (Delete) | |
1a4d82fc | 97 | I->setInitializer(nullptr); |
223e47cc LB |
98 | } |
99 | ||
100 | // Visit the Functions. | |
101 | for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) { | |
970d7e83 LB |
102 | bool Delete = |
103 | deleteStuff == (bool)Named.count(I) && !I->isDeclaration(); | |
104 | if (!Delete) { | |
223e47cc LB |
105 | if (I->hasAvailableExternallyLinkage()) |
106 | continue; | |
107 | } | |
108 | ||
85aaf69f | 109 | makeVisible(*I, Delete); |
970d7e83 LB |
110 | |
111 | if (Delete) | |
112 | I->deleteBody(); | |
113 | } | |
114 | ||
115 | // Visit the Aliases. | |
116 | for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end(); | |
117 | I != E;) { | |
118 | Module::alias_iterator CurI = I; | |
119 | ++I; | |
120 | ||
85aaf69f SL |
121 | bool Delete = deleteStuff == (bool)Named.count(CurI); |
122 | makeVisible(*CurI, Delete); | |
970d7e83 | 123 | |
1a4d82fc | 124 | if (Delete) { |
970d7e83 LB |
125 | Type *Ty = CurI->getType()->getElementType(); |
126 | ||
127 | CurI->removeFromParent(); | |
128 | llvm::Value *Declaration; | |
129 | if (FunctionType *FTy = dyn_cast<FunctionType>(Ty)) { | |
130 | Declaration = Function::Create(FTy, GlobalValue::ExternalLinkage, | |
131 | CurI->getName(), &M); | |
132 | ||
133 | } else { | |
134 | Declaration = | |
135 | new GlobalVariable(M, Ty, false, GlobalValue::ExternalLinkage, | |
1a4d82fc | 136 | nullptr, CurI->getName()); |
970d7e83 LB |
137 | |
138 | } | |
139 | CurI->replaceAllUsesWith(Declaration); | |
140 | delete CurI; | |
141 | } | |
223e47cc LB |
142 | } |
143 | ||
144 | return true; | |
145 | } | |
146 | }; | |
147 | ||
148 | char GVExtractorPass::ID = 0; | |
149 | } | |
150 | ||
85aaf69f | 151 | ModulePass *llvm::createGVExtractionPass(std::vector<GlobalValue *> &GVs, |
223e47cc LB |
152 | bool deleteFn) { |
153 | return new GVExtractorPass(GVs, deleteFn); | |
154 | } |