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