Home | History | Annotate | Download | only in Orc
      1 //===---- IndirectionUtils.cpp - Utilities for call indirection in Orc ----===//
      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 #include "llvm/ADT/STLExtras.h"
     11 #include "llvm/ADT/Triple.h"
     12 #include "llvm/ExecutionEngine/Orc/IndirectionUtils.h"
     13 #include "llvm/IR/CallSite.h"
     14 #include "llvm/IR/IRBuilder.h"
     15 #include "llvm/Transforms/Utils/Cloning.h"
     16 #include <set>
     17 #include <sstream>
     18 
     19 namespace llvm {
     20 namespace orc {
     21 
     22 void JITCompileCallbackManager::anchor() {}
     23 void IndirectStubsManager::anchor() {}
     24 
     25 Constant* createIRTypedAddress(FunctionType &FT, TargetAddress Addr) {
     26   Constant *AddrIntVal =
     27     ConstantInt::get(Type::getInt64Ty(FT.getContext()), Addr);
     28   Constant *AddrPtrVal =
     29     ConstantExpr::getCast(Instruction::IntToPtr, AddrIntVal,
     30                           PointerType::get(&FT, 0));
     31   return AddrPtrVal;
     32 }
     33 
     34 GlobalVariable* createImplPointer(PointerType &PT, Module &M,
     35                                   const Twine &Name, Constant *Initializer) {
     36   auto IP = new GlobalVariable(M, &PT, false, GlobalValue::ExternalLinkage,
     37                                Initializer, Name, nullptr,
     38                                GlobalValue::NotThreadLocal, 0, true);
     39   IP->setVisibility(GlobalValue::HiddenVisibility);
     40   return IP;
     41 }
     42 
     43 void makeStub(Function &F, Value &ImplPointer) {
     44   assert(F.isDeclaration() && "Can't turn a definition into a stub.");
     45   assert(F.getParent() && "Function isn't in a module.");
     46   Module &M = *F.getParent();
     47   BasicBlock *EntryBlock = BasicBlock::Create(M.getContext(), "entry", &F);
     48   IRBuilder<> Builder(EntryBlock);
     49   LoadInst *ImplAddr = Builder.CreateLoad(&ImplPointer);
     50   std::vector<Value*> CallArgs;
     51   for (auto &A : F.args())
     52     CallArgs.push_back(&A);
     53   CallInst *Call = Builder.CreateCall(ImplAddr, CallArgs);
     54   Call->setTailCall();
     55   Call->setAttributes(F.getAttributes());
     56   if (F.getReturnType()->isVoidTy())
     57     Builder.CreateRetVoid();
     58   else
     59     Builder.CreateRet(Call);
     60 }
     61 
     62 // Utility class for renaming global values and functions during partitioning.
     63 class GlobalRenamer {
     64 public:
     65 
     66   static bool needsRenaming(const Value &New) {
     67     return !New.hasName() || New.getName().startswith("\01L");
     68   }
     69 
     70   const std::string& getRename(const Value &Orig) {
     71     // See if we have a name for this global.
     72     {
     73       auto I = Names.find(&Orig);
     74       if (I != Names.end())
     75         return I->second;
     76     }
     77 
     78     // Nope. Create a new one.
     79     // FIXME: Use a more robust uniquing scheme. (This may blow up if the user
     80     //        writes a "__orc_anon[[:digit:]]* method).
     81     unsigned ID = Names.size();
     82     std::ostringstream NameStream;
     83     NameStream << "__orc_anon" << ID++;
     84     auto I = Names.insert(std::make_pair(&Orig, NameStream.str()));
     85     return I.first->second;
     86   }
     87 private:
     88   DenseMap<const Value*, std::string> Names;
     89 };
     90 
     91 static void raiseVisibilityOnValue(GlobalValue &V, GlobalRenamer &R) {
     92   if (V.hasLocalLinkage()) {
     93     if (R.needsRenaming(V))
     94       V.setName(R.getRename(V));
     95     V.setLinkage(GlobalValue::ExternalLinkage);
     96     V.setVisibility(GlobalValue::HiddenVisibility);
     97   }
     98   V.setUnnamedAddr(false);
     99   assert(!R.needsRenaming(V) && "Invalid global name.");
    100 }
    101 
    102 void makeAllSymbolsExternallyAccessible(Module &M) {
    103   GlobalRenamer Renamer;
    104 
    105   for (auto &F : M)
    106     raiseVisibilityOnValue(F, Renamer);
    107 
    108   for (auto &GV : M.globals())
    109     raiseVisibilityOnValue(GV, Renamer);
    110 
    111   for (auto &A : M.aliases())
    112     raiseVisibilityOnValue(A, Renamer);
    113 }
    114 
    115 Function* cloneFunctionDecl(Module &Dst, const Function &F,
    116                             ValueToValueMapTy *VMap) {
    117   assert(F.getParent() != &Dst && "Can't copy decl over existing function.");
    118   Function *NewF =
    119     Function::Create(cast<FunctionType>(F.getType()->getElementType()),
    120                      F.getLinkage(), F.getName(), &Dst);
    121   NewF->copyAttributesFrom(&F);
    122 
    123   if (VMap) {
    124     (*VMap)[&F] = NewF;
    125     auto NewArgI = NewF->arg_begin();
    126     for (auto ArgI = F.arg_begin(), ArgE = F.arg_end(); ArgI != ArgE;
    127          ++ArgI, ++NewArgI)
    128       (*VMap)[&*ArgI] = &*NewArgI;
    129   }
    130 
    131   return NewF;
    132 }
    133 
    134 void moveFunctionBody(Function &OrigF, ValueToValueMapTy &VMap,
    135                       ValueMaterializer *Materializer,
    136                       Function *NewF) {
    137   assert(!OrigF.isDeclaration() && "Nothing to move");
    138   if (!NewF)
    139     NewF = cast<Function>(VMap[&OrigF]);
    140   else
    141     assert(VMap[&OrigF] == NewF && "Incorrect function mapping in VMap.");
    142   assert(NewF && "Function mapping missing from VMap.");
    143   assert(NewF->getParent() != OrigF.getParent() &&
    144          "moveFunctionBody should only be used to move bodies between "
    145          "modules.");
    146 
    147   SmallVector<ReturnInst *, 8> Returns; // Ignore returns cloned.
    148   CloneFunctionInto(NewF, &OrigF, VMap, /*ModuleLevelChanges=*/true, Returns,
    149                     "", nullptr, nullptr, Materializer);
    150   OrigF.deleteBody();
    151 }
    152 
    153 GlobalVariable* cloneGlobalVariableDecl(Module &Dst, const GlobalVariable &GV,
    154                                         ValueToValueMapTy *VMap) {
    155   assert(GV.getParent() != &Dst && "Can't copy decl over existing global var.");
    156   GlobalVariable *NewGV = new GlobalVariable(
    157       Dst, GV.getType()->getElementType(), GV.isConstant(),
    158       GV.getLinkage(), nullptr, GV.getName(), nullptr,
    159       GV.getThreadLocalMode(), GV.getType()->getAddressSpace());
    160   NewGV->copyAttributesFrom(&GV);
    161   if (VMap)
    162     (*VMap)[&GV] = NewGV;
    163   return NewGV;
    164 }
    165 
    166 void moveGlobalVariableInitializer(GlobalVariable &OrigGV,
    167                                    ValueToValueMapTy &VMap,
    168                                    ValueMaterializer *Materializer,
    169                                    GlobalVariable *NewGV) {
    170   assert(OrigGV.hasInitializer() && "Nothing to move");
    171   if (!NewGV)
    172     NewGV = cast<GlobalVariable>(VMap[&OrigGV]);
    173   else
    174     assert(VMap[&OrigGV] == NewGV &&
    175            "Incorrect global variable mapping in VMap.");
    176   assert(NewGV->getParent() != OrigGV.getParent() &&
    177          "moveGlobalVariable should only be used to move initializers between "
    178          "modules");
    179 
    180   NewGV->setInitializer(MapValue(OrigGV.getInitializer(), VMap, RF_None,
    181                                  nullptr, Materializer));
    182 }
    183 
    184 GlobalAlias* cloneGlobalAliasDecl(Module &Dst, const GlobalAlias &OrigA,
    185                                   ValueToValueMapTy &VMap) {
    186   assert(OrigA.getAliasee() && "Original alias doesn't have an aliasee?");
    187   auto *NewA = GlobalAlias::create(OrigA.getValueType(),
    188                                    OrigA.getType()->getPointerAddressSpace(),
    189                                    OrigA.getLinkage(), OrigA.getName(), &Dst);
    190   NewA->copyAttributesFrom(&OrigA);
    191   VMap[&OrigA] = NewA;
    192   return NewA;
    193 }
    194 
    195 } // End namespace orc.
    196 } // End namespace llvm.
    197