ExtractGV.cpp revision 36b56886974eae4f9c5ebc96befd3e7bfe5de338
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>
22using 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.
28static 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
56namespace {
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) override {
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
152ModulePass *llvm::createGVExtractionPass(std::vector<GlobalValue*>& GVs,
153                                         bool deleteFn) {
154  return new GVExtractorPass(GVs, deleteFn);
155}
156