Generator::~Generator() { std::map<std::string, llvm::IRBuilder<> *> tors = { { "llvm.global_ctors", ctor }, { "llvm.global_dtors", dtor } }; auto base_str = llvm::PointerType::get(llvm::Type::getInt8Ty(mod->getContext()), 0); auto int32_ty = llvm::Type::getInt32Ty(mod->getContext()); llvm::Type *struct_elements[] = { int32_ty, llvm::PointerType::get(llvm::FunctionType::get( llvm::Type::getVoidTy(mod->getContext()), false), 0), base_str }; auto struct_ty = llvm::StructType::create(struct_elements); auto array_ty = llvm::ArrayType::get(struct_ty, 1); for (auto &tor : tors) { tor.second->CreateRetVoid(); auto link = new llvm::GlobalVariable(*mod, array_ty, false, llvm::GlobalVariable::AppendingLinkage, 0, tor.first); llvm::Constant *constants[] = { llvm::ConstantStruct::get( struct_ty, llvm::ConstantInt::get(int32_ty, 65535), tor.second->GetInsertBlock()->getParent(), llvm::ConstantPointerNull::get(base_str)) }; link->setInitializer(llvm::ConstantArray::get(array_ty, constants)); delete tor.second; } }
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; }
llvm::Constant *Generator::createString(const std::string &str) { auto iterator = constant_pool.find(str); if (iterator != constant_pool.end()) { return iterator->second; } auto array = llvm::ConstantDataArray::getString(mod->getContext(), str); auto global_variable = new llvm::GlobalVariable( *mod, llvm::ArrayType::get(llvm::Type::getInt8Ty(mod->getContext()), str.length() + 1), true, llvm::GlobalValue::PrivateLinkage, 0, ".str"); global_variable->setAlignment(1); global_variable->setInitializer(array); auto zero = llvm::ConstantInt::get(llvm::Type::getInt8Ty(mod->getContext()), 0); std::vector<llvm::Value *> indicies; indicies.push_back(zero); indicies.push_back(zero); auto result = llvm::ConstantExpr::getGetElementPtr( global_variable->getValueType(), global_variable, indicies); constant_pool[str] = result; return result; }