| 152 | } |
| 153 | |
| 154 | Status LlvmCodeGen::InitializeLlvm(const char* procname, bool load_backend) { |
| 155 | DCHECK(!llvm_initialized_); |
| 156 | // Treat all functions as having the inline hint |
| 157 | std::array<const char*, 2> argv = { { procname, "-inline-threshold=325" } }; |
| 158 | CHECK(llvm::cl::ParseCommandLineOptions(argv.size(), argv.data())); |
| 159 | llvm::remove_fatal_error_handler(); |
| 160 | llvm::install_fatal_error_handler(LlvmCodegenHandleError); |
| 161 | // These functions can *only* be called once per process and are used to set up |
| 162 | // LLVM subsystems for code generation targeting the machine we're running on. |
| 163 | llvm::InitializeNativeTarget(); |
| 164 | llvm::InitializeNativeTargetAsmPrinter(); |
| 165 | llvm::InitializeNativeTargetAsmParser(); |
| 166 | llvm::InitializeNativeTargetDisassembler(); |
| 167 | llvm_initialized_ = true; |
| 168 | |
| 169 | if (load_backend) { |
| 170 | string path; |
| 171 | // For test env, we have to load libfesupport.so to provide sym for LLVM. |
| 172 | PathBuilder::GetFullBuildPath("service/libfesupport.so", &path); |
| 173 | bool failed = llvm::sys::DynamicLibrary::LoadLibraryPermanently(path.c_str()); |
| 174 | DCHECK_EQ(failed, 0); |
| 175 | } |
| 176 | |
| 177 | cpu_name_ = llvm::sys::getHostCPUName().str(); |
| 178 | LOG(INFO) << "CPU class for runtime code generation: " << cpu_name_; |
| 179 | GetHostCPUAttrs(&cpu_attrs_); |
| 180 | LOG(INFO) << "Detected CPU flags: " << boost::join(cpu_attrs_, ","); |
| 181 | cpu_attrs_ = ApplyCpuAttrWhitelist(cpu_attrs_); |
| 182 | target_features_attr_ = boost::join(cpu_attrs_, ","); |
| 183 | LOG(INFO) << "CPU flags enabled for runtime code generation: " << target_features_attr_; |
| 184 | |
| 185 | // Write an empty map file for perf to find. |
| 186 | if (FLAGS_perf_map) CodegenSymbolEmitter::WritePerfMap(); |
| 187 | |
| 188 | ObjectPool init_pool; |
| 189 | scoped_ptr<LlvmCodeGen> init_codegen; |
| 190 | RETURN_IF_ERROR(LlvmCodeGen::CreateFromMemory( |
| 191 | nullptr, &init_pool, nullptr, "init", &init_codegen)); |
| 192 | // LLVM will construct "use" lists only when the entire module is materialized. |
| 193 | RETURN_IF_ERROR(init_codegen->MaterializeModule()); |
| 194 | |
| 195 | // Validate the module by verifying that functions for all IRFunction::Type |
| 196 | // can be found. |
| 197 | for (int i = IRFunction::FN_START; i < IRFunction::FN_END; ++i) { |
| 198 | DCHECK_EQ(FN_MAPPINGS[i].fn, i); |
| 199 | const string& fn_name = FN_MAPPINGS[i].fn_name; |
| 200 | if (init_codegen->module_->getFunction(fn_name) == nullptr) { |
| 201 | const string& err_msg = Substitute("Failed to find function $0", fn_name); |
| 202 | LOG(ERROR) << err_msg; |
| 203 | return Status(err_msg); |
| 204 | } |
| 205 | } |
| 206 | |
| 207 | // Initialize the global shared call graph. |
| 208 | shared_call_graph_.Init(init_codegen->module_); |
| 209 | init_codegen->Close(); |
| 210 | return Status::OK(); |
| 211 | } |
nothing calls this directly
no test coverage detected