Example #1
0
/**
  * コード生成実行
  * @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;
}
Example #2
0
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;
}