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