Home | History | Annotate | Download | only in IPO
      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 namespace {
     25   /// @brief A pass to extract specific functions and their dependencies.
     26   class GVExtractorPass : public ModulePass {
     27     SetVector<GlobalValue *> Named;
     28     bool deleteStuff;
     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     ///
     36     explicit GVExtractorPass(std::vector<GlobalValue*>& GVs, bool deleteS = true)
     37       : ModulePass(ID), Named(GVs.begin(), GVs.end()), deleteStuff(deleteS) {}
     38 
     39     bool runOnModule(Module &M) {
     40       // Visit the global inline asm.
     41       if (!deleteStuff)
     42         M.setModuleInlineAsm("");
     43 
     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.
     50 
     51       // Visit the GlobalVariables.
     52       for (Module::global_iterator I = M.global_begin(), E = M.global_end();
     53            I != E; ++I) {
     54         bool Delete =
     55           deleteStuff == (bool)Named.count(I) && !I->isDeclaration();
     56         if (!Delete) {
     57           if (I->hasAvailableExternallyLinkage())
     58             continue;
     59           if (I->getName() == "llvm.global_ctors")
     60             continue;
     61         }
     62 
     63         bool Local = I->isDiscardableIfUnused();
     64         if (Local)
     65           I->setVisibility(GlobalValue::HiddenVisibility);
     66 
     67         if (Local || Delete)
     68           I->setLinkage(GlobalValue::ExternalLinkage);
     69 
     70         if (Delete)
     71           I->setInitializer(0);
     72       }
     73 
     74       // Visit the Functions.
     75       for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) {
     76         bool Delete =
     77           deleteStuff == (bool)Named.count(I) && !I->isDeclaration();
     78         if (!Delete) {
     79           if (I->hasAvailableExternallyLinkage())
     80             continue;
     81         }
     82 
     83         bool Local = I->isDiscardableIfUnused();
     84         if (Local)
     85           I->setVisibility(GlobalValue::HiddenVisibility);
     86 
     87         if (Local || Delete)
     88           I->setLinkage(GlobalValue::ExternalLinkage);
     89 
     90         if (Delete)
     91           I->deleteBody();
     92       }
     93 
     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 
    100         if (CurI->isDiscardableIfUnused()) {
    101           CurI->setVisibility(GlobalValue::HiddenVisibility);
    102           CurI->setLinkage(GlobalValue::ExternalLinkage);
    103         }
    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 
    125       return true;
    126     }
    127   };
    128 
    129   char GVExtractorPass::ID = 0;
    130 }
    131 
    132 ModulePass *llvm::createGVExtractionPass(std::vector<GlobalValue*>& GVs,
    133                                          bool deleteFn) {
    134   return new GVExtractorPass(GVs, deleteFn);
    135 }
    136