/** * コード生成実行 * @param TranslationUnitAST Module名(入力ファイル名) * @return 成功時:true 失敗時:false */ bool CodeGen::doCodeGen(TranslationUnitAST &tunit, std::string name, std::string link_file, bool with_jit=false){ if(!generateTranslationUnit(tunit, name)){ return false; } //LinkFileの指定があったらModuleをリンク if( !link_file.empty() && !linkModule(Mod, link_file) ) return false; //JITのフラグが立っていたらJIT if(with_jit){ llvm::ExecutionEngine *EE = llvm::EngineBuilder(Mod).create(); llvm::EngineBuilder(Mod).create(); llvm::Function *F; if(!(F=Mod->getFunction("main"))) return false; int (*fp)() = (int (*)())EE->getPointerToFunction(F); fprintf(stderr,"%d\n",fp()); } return true; }
int Generator::run(std::vector<const char *> *file_paths, std::vector<const char *> *bc_file_paths, std::vector<const char *> *compile_lib_paths, std::vector<const char *> *include_paths, std::vector<const char *> *module_paths, std::vector<const char *> *static_module_names, std::vector<const char *> *cto_module_names, const char *module_name, int debug, int produce, int optlevel, int remove_macros, int no_common, int no_dale_stdlib, int static_mods_all, int enable_cto, std::vector<std::string> *shared_object_paths, FILE *output_file) { if (!file_paths->size()) { return 0; } NativeTypes nt; TypeRegister tr; llvm::ExecutionEngine *ee = NULL; std::set<std::string> cto_modules; for (std::vector<const char*>::iterator b = cto_module_names->begin(), e = cto_module_names->end(); b != e; ++b) { cto_modules.insert(std::string(*b)); } /* On OS X, SYSTEM_PROCESSOR is i386 even when the underlying * processor is x86-64, hence the extra check here. */ bool is_x86_64 = ((!strcmp(SYSTEM_PROCESSOR, "x86_64")) || ((!strcmp(SYSTEM_PROCESSOR, "amd64"))) || ((!strcmp(SYSTEM_NAME, "Darwin")) && (sizeof(char *) == 8))); init_introspection_functions(); llvm::Module *last_module = NULL; Module::Reader mr(module_paths, shared_object_paths, include_paths); for (std::vector<const char*>::iterator b = compile_lib_paths->begin(), e = compile_lib_paths->end(); b != e; ++b) { mr.addDynamicLibrary((*b), false, false); } const char *libdrt_path = NULL; if (!no_dale_stdlib) { FILE *drt_file = NULL; if ((drt_file = fopen(DALE_LIBRARY_PATH "/libdrt.so", "r"))) { libdrt_path = DALE_LIBRARY_PATH "/libdrt.so"; } else if ((drt_file = fopen("./libdrt.so", "r"))) { libdrt_path = "./libdrt.so"; } else { error("unable to find libdrt.so"); } mr.addDynamicLibrary(libdrt_path, false, false); int res = fclose(drt_file); if (res != 0) { error("unable to close %s", libdrt_path, true); } } if (!module_name && libdrt_path) { shared_object_paths->push_back(libdrt_path); } Units units(&mr); units.cto = enable_cto; units.no_common = no_common; units.no_dale_stdlib = no_dale_stdlib; Context *ctx = NULL; llvm::Module *mod = NULL; llvm::Linker *linker = NULL; ErrorReporter er(""); if (module_name) { const char *last_slash = strrchr(module_name, '/'); std::string bare_module_name; if (!last_slash) { last_slash = module_name; bare_module_name = std::string(last_slash); } else { bare_module_name = std::string(last_slash + 1); } if (bare_module_name.length() > 0) { if (!isValidModuleName(&bare_module_name)) { Error *e = new Error( ErrorInst::InvalidModuleName, NULL, bare_module_name.c_str() ); er.addError(e); return 0; } } int diff = last_slash - module_name; units.module_name = std::string(module_name); units.module_name.replace(diff + 1, 0, "lib"); } for (std::vector<const char*>::iterator b = file_paths->begin(), e = file_paths->end(); b != e; ++b) { const char *filename = *b; assert(!units.size()); Unit *unit = new Unit(filename, &units, &er, &nt, &tr, NULL, is_x86_64); units.push(unit); ctx = unit->ctx; mod = unit->module; linker = unit->linker; llvm::Triple triple(mod->getTargetTriple()); if (triple.getTriple().empty()) { triple.setTriple(getTriple()); } mod->setDataLayout((is_x86_64) ? x86_64_layout : x86_32_layout); llvm::EngineBuilder eb = llvm::EngineBuilder(mod); eb.setEngineKind(llvm::EngineKind::JIT); ee = eb.create(); assert(ee); ee->InstallLazyFunctionCreator(&lazyFunctionCreator); unit->ee = ee; unit->mp->ee = ee; CommonDecl::addVarargsFunctions(unit); if (!no_common) { if (no_dale_stdlib) { unit->addCommonDeclarations(); } else { std::vector<const char*> import_forms; mr.run(ctx, mod, nullNode(), "drt", &import_forms); units.top()->mp->setPoolfree(); } } std::vector<Node*> nodes; for (;;) { int error_count = er.getErrorTypeCount(ErrorType::Error); Node *top = units.top()->parser->getNextList(); if (top) { nodes.push_back(top); } if (er.getErrorTypeCount(ErrorType::Error) > error_count) { er.flush(); continue; } if (!top) { er.flush(); break; } if (!top->is_token && !top->is_list) { units.pop(); if (!units.empty()) { Unit *unit = units.top(); ctx = unit->ctx; mod = unit->module; linker = unit->linker; continue; } break; } FormTopLevelInstParse(&units, top); er.flush(); } if (remove_macros) { ctx->eraseLLVMMacros(); } if (dale::pool_free_fptr) { ee->freeMachineCodeForFunction(dale::pool_free_fn); } if (last_module) { linkModule(linker, last_module); } last_module = mod; for (std::vector<Node *>::iterator b = nodes.begin(), e = nodes.end(); b != e; ++b) { delete (*b); } } if (remove_macros) { ctx->eraseLLVMMacros(); } if (er.getErrorTypeCount(ErrorType::Error)) { return 0; } if (bc_file_paths) { for (std::vector<const char*>::iterator b = bc_file_paths->begin(), e = bc_file_paths->end(); b != e; ++b) { linkFile(linker, *b); } } /* At optlevel 3, things go quite awry when making libraries, due * to the argumentPromotionPass. So set it to 2, unless LTO has * also been requested (optlevel == 4). */ bool lto = false; if (optlevel == 3) { optlevel = 2; } else if (optlevel == 4) { optlevel = 3; lto = true; } llvm::TargetMachine *target_machine = getTargetMachine(last_module); llvm::raw_fd_ostream ostream(fileno(output_file), false); llvm::PassManager pass_manager; addDataLayout(&pass_manager, mod); pass_manager.add(llvm::createPostDomTree()); llvm::PassManagerBuilder pass_manager_builder; pass_manager_builder.OptLevel = optlevel; pass_manager_builder.DisableUnitAtATime = true; if (optlevel > 0) { if (lto) { pass_manager_builder.DisableUnitAtATime = false; } pass_manager_builder.populateModulePassManager(pass_manager); if (lto) { pass_manager_builder.populateLTOPassManager(pass_manager, true, true); } } if (units.module_name.size() > 0) { Module::Writer mw(units.module_name, ctx, mod, &pass_manager, &(mr.included_once_tags), &(mr.included_modules), units.cto); mw.run(); return 1; } std::map<std::string, llvm::Module*> *dtm_modules = &(mr.dtm_modules); std::map<std::string, std::string> *dtm_nm_modules = &(mr.dtm_nm_modules); bool reget_pointers = true; std::map<std::string, llvm::Module *> static_dtm_modules; if (static_mods_all || (static_module_names->size() > 0)) { if (remove_macros) { for (std::map<std::string, std::string>::iterator b = dtm_nm_modules->begin(), e = dtm_nm_modules->end(); b != e; ++b) { static_dtm_modules.insert( std::pair<std::string, llvm::Module*>( b->first, mr.loadModule(&(b->second)) ) ); } } else { static_dtm_modules = *dtm_modules; } reget_pointers = false; } if (static_mods_all) { for (std::map<std::string, llvm::Module *>::iterator b = static_dtm_modules.begin(), e = static_dtm_modules.end(); b != e; ++b) { if (cto_modules.find(b->first) == cto_modules.end()) { linkModule(linker, b->second); } } } else if (static_module_names->size() > 0) { for (std::vector<const char *>::iterator b = static_module_names->begin(), e = static_module_names->end(); b != e; ++b) { std::map<std::string, llvm::Module *>::iterator found = static_dtm_modules.find(std::string(*b)); if (found != static_dtm_modules.end()) { linkModule(linker, found->second); } } reget_pointers = false; } if (reget_pointers) { ctx->regetPointers(mod); } if (remove_macros) { ctx->eraseLLVMMacrosAndCTOFunctions(); } llvm::formatted_raw_ostream *ostream_formatted = new llvm::formatted_raw_ostream( ostream, llvm::formatted_raw_ostream::DELETE_STREAM ); if (produce == IR) { addPrintModulePass(&pass_manager, &ostream); } else if (produce == ASM) { target_machine->setAsmVerbosityDefault(true); llvm::CodeGenOpt::Level level = llvm::CodeGenOpt::Default; bool res = target_machine->addPassesToEmitFile( pass_manager, *ostream_formatted, llvm::TargetMachine::CGFT_AssemblyFile, level, NULL); assert(!res && "unable to add passes to emit file"); _unused(res); } if (debug) { mod->dump(); } if (debug) { llvm::verifyModule(*mod); } pass_manager.run(*mod); if (produce == BitCode) { llvm::WriteBitcodeToFile(mod, ostream); } ostream_formatted->flush(); ostream.flush(); return 1; }