Esempio n. 1
0
bool FormTopLevelIncludeParse(Units *units, Node *node) {
    Context *ctx = units->top()->ctx;

    if (!ctx->er->assertArgNums("include", node, 1, 1)) {
        return false;
    }

    std::vector<Node *> *lst = node->list;
    Node *path_node = (*lst)[1];
    path_node = units->top()->mp->parsePotentialMacroCall(path_node);
    if (!path_node) {
        return false;
    }
    if (!ctx->er->assertArgIsAtom("include", path_node, "1")) {
        return false;
    }
    if (!ctx->er->assertAtomIsStringLiteral("include", path_node,
                                            "1")) {
        return false;
    }

    std::string path_buf;

    FILE *include_file = NULL;
    for (std::vector<const char *>::iterator
             b = units->mr->include_directory_paths.begin(),
             e = units->mr->include_directory_paths.end();
         b != e; ++b) {
        path_buf.clear();
        path_buf.append((*b));
        if (*(path_buf.rbegin()) != '/') {
            path_buf.push_back('/');
        }
        path_buf.append(path_node->token->str_value.c_str());
        include_file = fopen(path_buf.c_str(), "r");
        if (include_file) {
            break;
        }
    }

    if (!include_file) {
        Error *e = new Error(FileError, path_node, path_buf.c_str(),
                             strerror(errno));
        ctx->er->addError(e);
        return false;
    }

    Lexer *lxr = new Lexer(include_file);
    Parser parser(lxr, ctx->er, strdup(path_buf.c_str()));

    int error_count = ctx->er->getErrorTypeCount(ErrorType::Error);
    std::vector<Node *> *do_nodes = new std::vector<Node *>();
    Token *do_token = new Token(TokenType::String);
    do_token->str_value.append("do");
    do_nodes->push_back(new Node(do_token));
    for (;;) {
        Node *new_top = parser.getNextList();
        if (!new_top) {
            break;
        }
        if (!new_top->is_token && !new_top->is_list) {
            break;
        }
        if (new_top->is_list && new_top->list->size() &&
            new_top->list->at(0)->token &&
            (new_top->list->at(0)->token->str_value.compare("once") ==
             0)) {
            if (!ctx->er->assertArgNums("once", new_top, 1, 1)) {
                return false;
            }
            std::vector<Node *> *lst = new_top->list;
            Node *once_tag_node = (*lst)[1];
            once_tag_node = units->top()->mp->parsePotentialMacroCall(
                once_tag_node);
            if (!once_tag_node) {
                return false;
            }
            if (!ctx->er->assertArgIsAtom("once", once_tag_node, "1")) {
                return false;
            }
            const char *once_name =
                once_tag_node->token->str_value.c_str();
            std::string once_tag(once_name);

            if (units->mr->included_once_tags.find(once_tag) !=
                units->mr->included_once_tags.end()) {
                return true;
            }
            units->mr->included_once_tags.insert(once_tag);
            units->top()->once_tag = once_tag;
            units->top()->setOnceTag(once_tag);
            continue;
        }
        do_nodes->push_back(new_top);
    }
    if (ctx->er->getErrorTypeCount(ErrorType::Error) > error_count) {
        return false;
    }
    Node *wrapper = new Node(do_nodes);

    return FormTopLevelInstParse(units, wrapper);
}
Esempio n. 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;
}