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