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