llvm::GlobalVariable* JitCodeSpecializer::_clone_global_variable(SpecializationContext& context, const llvm::GlobalVariable& global_variable) const { // If the global variable already exists in the module, there is no point in cloning it again if (auto global = context.module->getGlobalVariable(global_variable.getName())) { return global; } // Create a new global variable with the same type, attributes, and properties const auto cloned_global = llvm::dyn_cast<llvm::GlobalVariable>( context.module->getOrInsertGlobal(global_variable.getName(), global_variable.getValueType())); cloned_global->setLinkage(global_variable.getLinkage()); cloned_global->setThreadLocalMode(global_variable.getThreadLocalMode()); cloned_global->copyAttributesFrom(&global_variable); if (!global_variable.isDeclaration()) { if (global_variable.hasInitializer()) { // Instruct LLVM to perform the cloning of the actual value (i.e., initializer) of the variable cloned_global->setInitializer(llvm::MapValue(global_variable.getInitializer(), context.llvm_value_map)); } // Clone LLVM metadata for the global variable llvm::SmallVector<std::pair<uint32_t, llvm::MDNode*>, 1> metadata_nodes; global_variable.getAllMetadata(metadata_nodes); for (const auto& metadata_node : metadata_nodes) { cloned_global->addMetadata(metadata_node.first, *MapMetadata(metadata_node.second, context.llvm_value_map, llvm::RF_MoveDistinctMDs)); } } return cloned_global; }
void cloneModuleFlagsMetadata(Module &Dst, const Module &Src, ValueToValueMapTy &VMap) { auto *MFs = Src.getModuleFlagsMetadata(); if (!MFs) return; for (auto *MF : MFs->operands()) Dst.addModuleFlag(MapMetadata(MF, VMap)); }
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->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<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)); } }