| 1263 | } |
| 1264 | |
| 1265 | Status LlvmCodeGen::FinalizeModule(string* module_id) { |
| 1266 | DCHECK(!is_compiled_); |
| 1267 | is_compiled_ = true; |
| 1268 | |
| 1269 | if (FLAGS_unopt_module_dir.size() != 0) { |
| 1270 | string path = FLAGS_unopt_module_dir + "/" + id_ + "_unopt.ll"; |
| 1271 | fstream f(path.c_str(), fstream::out | fstream::trunc); |
| 1272 | if (f.fail()) { |
| 1273 | LOG(ERROR) << "Could not save IR to: " << path; |
| 1274 | } else { |
| 1275 | f << GetIR(true); |
| 1276 | f.close(); |
| 1277 | LOG(INFO) << "Saved unoptimized IR to " << path; |
| 1278 | } |
| 1279 | } |
| 1280 | |
| 1281 | if (is_corrupt_) return Status("Module is corrupt."); |
| 1282 | SCOPED_TIMER(profile_->total_time_counter()); |
| 1283 | SCOPED_THREAD_COUNTER_MEASUREMENT(llvm_thread_counters_); |
| 1284 | |
| 1285 | // Clean up handcrafted functions that have not been finalized. Clean up is done by |
| 1286 | // deleting the function from the module. Any reference to deleted functions in the |
| 1287 | // module will crash LLVM and thus Impala during finalization of the module. |
| 1288 | stringstream ss; |
| 1289 | for (llvm::Function* fn : handcrafted_functions_) { |
| 1290 | if (finalized_functions_.find(fn) == finalized_functions_.end()) { |
| 1291 | ss << fn->getName().str() << "\n"; |
| 1292 | fn->eraseFromParent(); |
| 1293 | } |
| 1294 | } |
| 1295 | string non_finalized_fns_str = ss.str(); |
| 1296 | if (!non_finalized_fns_str.empty()) { |
| 1297 | LOG(INFO) << "For query " << PrintId(state_->query_id()) |
| 1298 | << " the following functions were not finalized and have been removed from " |
| 1299 | "the module:\n" |
| 1300 | << non_finalized_fns_str; |
| 1301 | } |
| 1302 | |
| 1303 | // Don't waste time optimizing module if there are no functions to JIT. This can happen |
| 1304 | // if the codegen object is created but no functions are successfully codegen'd. |
| 1305 | if (fns_to_jit_compile_.empty()) { |
| 1306 | DestroyModule(); |
| 1307 | return Status::OK(); |
| 1308 | } |
| 1309 | |
| 1310 | RETURN_IF_ERROR(FinalizeLazyMaterialization()); |
| 1311 | PruneModule(); |
| 1312 | |
| 1313 | bool codegen_cache_enabled = state_->codegen_cache_enabled() && codegen_cache_enabled_; |
| 1314 | CodeGenCacheKey cache_key; |
| 1315 | bool cache_hit = false; |
| 1316 | if (codegen_cache_enabled) { |
| 1317 | string bitcode; |
| 1318 | SCOPED_TIMER(codegen_cache_lookup_timer_); |
| 1319 | { |
| 1320 | SCOPED_TIMER(module_bitcode_gen_timer_); |
| 1321 | llvm::raw_string_ostream bitcode_stream(bitcode); |
| 1322 | llvm::WriteBitcodeToFile(module_, bitcode_stream); |