Example #1
0
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;
}
Example #2
0
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;
}