int Compiler::compile(bool compileOnly) { llvm::Target const *Target = NULL; llvm::TargetData *TD = NULL; llvm::TargetMachine *TM = NULL; std::string FeaturesStr; llvm::NamedMDNode const *PragmaMetadata; llvm::NamedMDNode const *ExportVarMetadata; llvm::NamedMDNode const *ExportFuncMetadata; llvm::NamedMDNode const *ObjectSlotMetadata; if (mModule == NULL) // No module was loaded return 0; // Create TargetMachine Target = llvm::TargetRegistry::lookupTarget(Triple, mError); if (hasError()) goto on_bcc_compile_error; if (!CPU.empty() || !Features.empty()) { llvm::SubtargetFeatures F; for (std::vector<std::string>::const_iterator I = Features.begin(), E = Features.end(); I != E; I++) { F.AddFeature(*I); } FeaturesStr = F.getString(); } #if defined(DEFAULT_X86_64_CODEGEN) // Data address in X86_64 architecture may reside in a far-away place TM = Target->createTargetMachine(Triple, CPU, FeaturesStr, llvm::Reloc::Static, llvm::CodeModel::Medium); #else // This is set for the linker (specify how large of the virtual addresses // we can access for all unknown symbols.) TM = Target->createTargetMachine(Triple, CPU, FeaturesStr, llvm::Reloc::Static, llvm::CodeModel::Small); #endif if (TM == NULL) { setError("Failed to create target machine implementation for the" " specified triple '" + Triple + "'"); goto on_bcc_compile_error; } // Get target data from Module TD = new llvm::TargetData(mModule); // Load named metadata ExportVarMetadata = mModule->getNamedMetadata(ExportVarMetadataName); ExportFuncMetadata = mModule->getNamedMetadata(ExportFuncMetadataName); PragmaMetadata = mModule->getNamedMetadata(PragmaMetadataName); ObjectSlotMetadata = mModule->getNamedMetadata(ObjectSlotMetadataName); // Perform link-time optimization if we have multiple modules if (mHasLinked) { runLTO(new llvm::TargetData(*TD), ExportVarMetadata, ExportFuncMetadata); } // Perform code generation #if USE_OLD_JIT if (runCodeGen(new llvm::TargetData(*TD), TM, ExportVarMetadata, ExportFuncMetadata) != 0) { goto on_bcc_compile_error; } #endif #if USE_MCJIT if (runMCCodeGen(new llvm::TargetData(*TD), TM) != 0) { goto on_bcc_compile_error; } if (compileOnly) return 0; // Load the ELF Object mRSExecutable = rsloaderCreateExec((unsigned char *)&*mEmittedELFExecutable.begin(), mEmittedELFExecutable.size(), &resolveSymbolAdapter, this); if (!mRSExecutable) { setError("Fail to load emitted ELF relocatable file"); goto on_bcc_compile_error; } if (ExportVarMetadata) { ScriptCompiled::ExportVarList &varList = mpResult->mExportVars; std::vector<std::string> &varNameList = mpResult->mExportVarsName; for (int i = 0, e = ExportVarMetadata->getNumOperands(); i != e; i++) { llvm::MDNode *ExportVar = ExportVarMetadata->getOperand(i); if (ExportVar != NULL && ExportVar->getNumOperands() > 1) { llvm::Value *ExportVarNameMDS = ExportVar->getOperand(0); if (ExportVarNameMDS->getValueID() == llvm::Value::MDStringVal) { llvm::StringRef ExportVarName = static_cast<llvm::MDString*>(ExportVarNameMDS)->getString(); varList.push_back( rsloaderGetSymbolAddress(mRSExecutable, ExportVarName.str().c_str())); varNameList.push_back(ExportVarName.str()); #if DEBUG_MCJIT_REFLECT LOGD("runMCCodeGen(): Exported Var: %s @ %p\n", ExportVarName.str().c_str(), varList.back()); #endif continue; } } varList.push_back(NULL); } } if (ExportFuncMetadata) { ScriptCompiled::ExportFuncList &funcList = mpResult->mExportFuncs; std::vector<std::string> &funcNameList = mpResult->mExportFuncsName; for (int i = 0, e = ExportFuncMetadata->getNumOperands(); i != e; i++) { llvm::MDNode *ExportFunc = ExportFuncMetadata->getOperand(i); if (ExportFunc != NULL && ExportFunc->getNumOperands() > 0) { llvm::Value *ExportFuncNameMDS = ExportFunc->getOperand(0); if (ExportFuncNameMDS->getValueID() == llvm::Value::MDStringVal) { llvm::StringRef ExportFuncName = static_cast<llvm::MDString*>(ExportFuncNameMDS)->getString(); funcList.push_back( rsloaderGetSymbolAddress(mRSExecutable, ExportFuncName.str().c_str())); funcNameList.push_back(ExportFuncName.str()); #if DEBUG_MCJIT_RELECT LOGD("runMCCodeGen(): Exported Func: %s @ %p\n", ExportFuncName.str().c_str(), funcList.back()); #endif } } } } #if DEBUG_MCJIT_DISASSEMBLER { // Get MC codegen emitted function name list size_t func_list_size = rsloaderGetFuncCount(mRSExecutable); std::vector<char const *> func_list(func_list_size, NULL); rsloaderGetFuncNameList(mRSExecutable, func_list_size, &*func_list.begin()); // Disassemble each function for (size_t i = 0; i < func_list_size; ++i) { void *func = rsloaderGetSymbolAddress(mRSExecutable, func_list[i]); if (func) { size_t size = rsloaderGetSymbolSize(mRSExecutable, func_list[i]); Disassemble(DEBUG_MCJIT_DISASSEMBLER_FILE, Target, TM, func_list[i], (unsigned char const *)func, size); } } } #endif #endif // Read pragma information from the metadata node of the module. if (PragmaMetadata) { ScriptCompiled::PragmaList &pragmaList = mpResult->mPragmas; for (int i = 0, e = PragmaMetadata->getNumOperands(); i != e; i++) { llvm::MDNode *Pragma = PragmaMetadata->getOperand(i); if (Pragma != NULL && Pragma->getNumOperands() == 2 /* should have exactly 2 operands */) { llvm::Value *PragmaNameMDS = Pragma->getOperand(0); llvm::Value *PragmaValueMDS = Pragma->getOperand(1); if ((PragmaNameMDS->getValueID() == llvm::Value::MDStringVal) && (PragmaValueMDS->getValueID() == llvm::Value::MDStringVal)) { llvm::StringRef PragmaName = static_cast<llvm::MDString*>(PragmaNameMDS)->getString(); llvm::StringRef PragmaValue = static_cast<llvm::MDString*>(PragmaValueMDS)->getString(); pragmaList.push_back( std::make_pair(std::string(PragmaName.data(), PragmaName.size()), std::string(PragmaValue.data(), PragmaValue.size()))); #if DEBUG_BCC_REFLECT LOGD("compile(): Pragma: %s -> %s\n", pragmaList.back().first.c_str(), pragmaList.back().second.c_str()); #endif } } } } if (ObjectSlotMetadata) { ScriptCompiled::ObjectSlotList &objectSlotList = mpResult->mObjectSlots; for (int i = 0, e = ObjectSlotMetadata->getNumOperands(); i != e; i++) { llvm::MDNode *ObjectSlot = ObjectSlotMetadata->getOperand(i); if (ObjectSlot != NULL && ObjectSlot->getNumOperands() == 1) { llvm::Value *SlotMDS = ObjectSlot->getOperand(0); if (SlotMDS->getValueID() == llvm::Value::MDStringVal) { llvm::StringRef Slot = static_cast<llvm::MDString*>(SlotMDS)->getString(); uint32_t USlot = 0; if (Slot.getAsInteger(10, USlot)) { setError("Non-integer object slot value '" + Slot.str() + "'"); goto on_bcc_compile_error; } objectSlotList.push_back(USlot); #if DEBUG_BCC_REFLECT LOGD("compile(): RefCount Slot: %s @ %u\n", Slot.str().c_str(), USlot); #endif } } } } on_bcc_compile_error: // LOGE("on_bcc_compiler_error"); if (TD) { delete TD; } if (TM) { delete TM; } if (mError.empty()) { return 0; } // LOGE(getErrorMessage()); return 1; }
void *Compiler::getSymbolAddress(char const *name) { return rsloaderGetSymbolAddress(mRSExecutable, name); }
void *ScriptCached::lookup(const char *name) { return rsloaderGetSymbolAddress(mRSExecutable, name); }