bool parse(Path_seq const& in, Path const& out, Config const& conf) { bool ok = true; for (Path const& p : in) { if (get_file_kind(p) == beaker_file) ok &= parse(p, conf); else { // FIXME: LLVM IR/BC or assembly could (should?) be // lowered and passed through to the link phase. That // would allow a module to contain native assembly, // and used internally via foreign declarations. std::cerr << "error: unknown input file\n"; return -1; } } if (!ok) return -1; // Elaborate the parse result. Elaborator elab(locs, syms); elab.elaborate(&mod); // Translate to LLVM. Generator gen; llvm::Module* ir = gen(&mod); // Write the output to an IR file, not the requested // output. That happens later. Path p = to_ir_file(out); // Write the result to the output file. std::error_code err; llvm::raw_fd_ostream ofs(p.string(), err, llvm::sys::fs::F_None); ofs << *ir; return true; }
int translator_main(int argc, char* argv[]) { // Intitialize various subsystems. // // TODO: Always initialize parsing components? init_colors(); init_symbols(syms); // TODO: Support extraction to other intermediate formats? // Maybe C, for example? Gimple? // // Note that an introspection tool would have a considerably // different interface. po::options_description common("options"); common.add_options() ("help", "print help message") ("version", "print version message") ("input,i", po::value<String>(), "specify the input file") ("output,o", po::value<String>(), "specify the output file") ("keep,k", "keep temporary files"); po::positional_options_description pos; pos.add("input", 1); po::options_description all; all.add(common); // Parse command line options. po::variables_map vm; try { po::store( po::command_line_parser(argc, argv) .options(all) .positional(pos) .run(), vm); po::notify(vm); } catch(std::exception& err) { std::cerr << "error: " << err.what() << "\n\n"; usage(std::cerr, all); return -1; } // Check for obvious flags first. if (vm.count("help")) { usage(std::cout, all); return 0; } if (vm.count ("version")) { // TODO: Generate the version number from the // build. std::cout << "beaker v0.0" << '\n'; return 0; } // Validate the input. if (!vm.count("input")) { std::cerr << "error: no input file given\n"; usage(std::cerr, all); return -1; } Path input = vm["input"].as<String>(); // Look for an output file. If not given, the default // will be to produce .asm. Note that the default output // file is generated in the current directory. Path output; if (!vm.count("output")) output = to_asm_file(input.filename()); else output = vm["output"].as<String>(); // Compile the input into LLVM. Path temp; if (get_file_kind(input) == beaker_file) { temp = to_ir_file(input.filename()); if (!compile(input, temp)) return -1; input = temp; } // Lower llvm input to assembly. if (!lower(input, output)) return -1; // Remove the temporary file. if (!temp.empty() && !vm.count("keep")) fs::remove(temp); return 0; }