#include "llvm/ExecutionEngine/Orc/CloneSubModule.h" #include "llvm/IR/Function.h" #include "llvm/IR/GlobalVariable.h" #include "llvm/IR/Module.h" #include "llvm/Transforms/Utils/Cloning.h" namespace llvm { namespace orc { void copyGVInitializer(GlobalVariable &New, const GlobalVariable &Orig, ValueToValueMapTy &VMap) { if (Orig.hasInitializer()) New.setInitializer(MapValue(Orig.getInitializer(), VMap)); } void copyFunctionBody(Function &New, const Function &Orig, ValueToValueMapTy &VMap) { if (!Orig.isDeclaration()) { Function::arg_iterator DestI = New.arg_begin(); for (Function::const_arg_iterator J = Orig.arg_begin(); J != Orig.arg_end(); ++J) { DestI->setName(J->getName()); VMap[J] = DestI++; } SmallVector Returns; // Ignore returns cloned. CloneFunctionInto(&New, &Orig, VMap, /*ModuleLevelChanges=*/true, Returns); } } void CloneSubModule(llvm::Module &Dst, const Module &Src, HandleGlobalVariableFtor HandleGlobalVariable, HandleFunctionFtor HandleFunction, bool CloneInlineAsm) { ValueToValueMapTy VMap; if (CloneInlineAsm) Dst.appendModuleInlineAsm(Src.getModuleInlineAsm()); // Copy global variables (but not initializers, yet). for (Module::const_global_iterator I = Src.global_begin(), E = Src.global_end(); I != E; ++I) { GlobalVariable *GV = new GlobalVariable( Dst, I->getType()->getElementType(), I->isConstant(), I->getLinkage(), (Constant *)nullptr, I->getName(), (GlobalVariable *)nullptr, I->getThreadLocalMode(), I->getType()->getAddressSpace()); GV->copyAttributesFrom(I); VMap[I] = GV; } // Loop over the functions in the module, making external functions as before for (Module::const_iterator I = Src.begin(), E = Src.end(); I != E; ++I) { Function *NF = Function::Create(cast(I->getType()->getElementType()), I->getLinkage(), I->getName(), &Dst); NF->copyAttributesFrom(I); VMap[I] = NF; } // Loop over the aliases in the module for (Module::const_alias_iterator I = Src.alias_begin(), E = Src.alias_end(); I != E; ++I) { auto *PTy = cast(I->getType()); auto *GA = GlobalAlias::create(PTy->getElementType(), PTy->getAddressSpace(), I->getLinkage(), I->getName(), &Dst); GA->copyAttributesFrom(I); VMap[I] = GA; } // Now that all of the things that global variable initializer can refer to // have been created, loop through and copy the global variable referrers // over... We also set the attributes on the global now. for (Module::const_global_iterator I = Src.global_begin(), E = Src.global_end(); I != E; ++I) { GlobalVariable &GV = *cast(VMap[I]); HandleGlobalVariable(GV, *I, VMap); } // Similarly, copy over function bodies now... // for (Module::const_iterator I = Src.begin(), E = Src.end(); I != E; ++I) { Function &F = *cast(VMap[I]); HandleFunction(F, *I, VMap); } // And aliases for (Module::const_alias_iterator I = Src.alias_begin(), E = Src.alias_end(); I != E; ++I) { GlobalAlias *GA = cast(VMap[I]); if (const Constant *C = I->getAliasee()) GA->setAliasee(MapValue(C, VMap)); } // And named metadata.... for (Module::const_named_metadata_iterator I = Src.named_metadata_begin(), E = Src.named_metadata_end(); I != E; ++I) { const NamedMDNode &NMD = *I; NamedMDNode *NewNMD = Dst.getOrInsertNamedMetadata(NMD.getName()); for (unsigned i = 0, e = NMD.getNumOperands(); i != e; ++i) NewNMD->addOperand(MapMetadata(NMD.getOperand(i), VMap)); } } } // End namespace orc. } // End namespace llvm.