diff options
Diffstat (limited to 'llvm/lib/ExecutionEngine/Orc/CloneSubModule.cpp')
-rw-r--r-- | llvm/lib/ExecutionEngine/Orc/CloneSubModule.cpp | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/llvm/lib/ExecutionEngine/Orc/CloneSubModule.cpp b/llvm/lib/ExecutionEngine/Orc/CloneSubModule.cpp new file mode 100644 index 00000000000..c9810097d7d --- /dev/null +++ b/llvm/lib/ExecutionEngine/Orc/CloneSubModule.cpp @@ -0,0 +1,106 @@ +#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<ReturnInst *, 8> 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<FunctionType>(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<PointerType>(I->getType()); + auto *GA = GlobalAlias::create(PTy, 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<GlobalVariable>(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<Function>(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<GlobalAlias>(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. |