int main(int argc, char *argv[]) { llvm::cl::SetVersionPrinter(PrintVersion); llvm::cl::ParseCommandLineOptions(argc, argv, "CFG to LLVM"); auto context = llvm::make_unique<llvm::LLVMContext>(); if (OS.empty()) { if (ListSupported || ListUnsupported) { OS = "linux"; // just need something } else { std::cerr << "-os must be specified" << std::endl; return EXIT_FAILURE; } } if (!(ListSupported || ListUnsupported || ListCFGFunctions) && EntryPoints.empty()) { std::cerr << "-entrypoint must be specified" << std::endl; return EXIT_FAILURE; } if (!InitArch(context.get(), OS, Arch)) { std::cerr << "Cannot initialize for arch " << Arch << " and OS " << OS << std::endl; return EXIT_FAILURE; } auto M = CreateModule(context.get()); if (!M) { return EXIT_FAILURE; } auto triple = M->getTargetTriple(); if (ListSupported || ListUnsupported) { ListArchSupportedInstructions(triple, llvm::outs(), ListSupported, ListUnsupported); return EXIT_SUCCESS; } if (InputFilename.empty()) { std::cerr << "Must specify an input file." << std::endl; return EXIT_FAILURE; } //reproduce NativeModule from CFG input argument try { std::unique_ptr<NativeModule> mod(ReadProtoBuf(InputFilename)); if (!mod) { std::cerr << "Unable to read module from CFG" << std::endl; return EXIT_FAILURE; } if (ListCFGFunctions) { PrintCFGFunctionList(mod.get(), Arch); return EXIT_SUCCESS; } //make sure the entry point list is correct before we start lifting the code const std::vector<NativeEntrySymbol> &module_entry_points = mod->getEntryPoints(); for (const auto &entry_point : EntryPoints) { auto it = std::find_if( module_entry_points.begin(), module_entry_points.end(), [&entry_point](const NativeEntrySymbol &symbol) -> bool { return (symbol.getName() == entry_point); } ); if (it == module_entry_points.end()) { std::cerr << "The following entry point could not be found: \"" << entry_point << "\". Aborting..." << std::endl; return EXIT_FAILURE; } } //now, convert it to an LLVM module ArchInitAttachDetach(M); if (!LiftCodeIntoModule(mod.get(), M)) { std::cerr << "Failure to convert to LLVM module!" << std::endl; return EXIT_FAILURE; } std::set<VA> entry_point_pcs; for (const auto &entry_point_name : EntryPoints) { auto entry_pc = FindSymbolInModule(mod.get(), entry_point_name); assert(entry_pc != static_cast<VA>( -1)); std::cerr << "Adding entry point: " << entry_point_name << std::endl << entry_point_name << " is implemented by sub_" << std::hex << entry_pc << std::endl; if ( !ArchAddEntryPointDriver(M, entry_point_name, entry_pc)) { return EXIT_FAILURE; } entry_point_pcs.insert(entry_pc); } RenameLiftedFunctions(mod.get(), M, entry_point_pcs); // will abort if verification fails if (llvm::verifyModule( *M, &llvm::errs())) { std::cerr << "Could not verify module!" << std::endl; return EXIT_FAILURE; } std::error_code ec; llvm::tool_output_file Out(OutputFilename.c_str(), ec, llvm::sys::fs::F_None); llvm::WriteBitcodeToFile(M, Out.os()); Out.keep(); } catch (std::exception &e) { std::cerr << "error: " << std::endl << e.what() << std::endl; return EXIT_FAILURE; } return EXIT_SUCCESS; }
int main(int argc, const char * argv[]) { // Usage Message (TODO: Improve) if (argc < 3) { std::cerr << "Usage: " << argv[0] << " <FileName>\n" << "Compiles the file given by <FileName>\n"; return 1; } // Read in the file passed as the first argument std::ifstream fileStream; fileStream.open(argv[1]); // We'll output to the file passed in as the second argument std::error_code ec; auto openflags = llvm::sys::fs::F_None; auto out = std::make_unique<llvm::tool_output_file>(argv[2], ec, openflags); if (ec) { std::cerr << argv[0] << ": " << ec.message() << "\n"; return 1; } // Parse it! auto lex = Lexer(&fileStream); auto stmts = parse(&lex); // std::cout << "Result of parsing: \n"; // for (auto &stmt : stmts) { // std::cout << *stmt << ";\n"; // } auto prgm = Program(); prgm.addItems(stmts); prgm.finalize(); auto mod = prgm.module; /* DEBUG */ // mod->dump(); llvm::InitializeNativeTarget(); llvm::InitializeNativeTargetAsmPrinter(); llvm::InitializeNativeTargetAsmParser(); llvm::PassRegistry *registry = llvm::PassRegistry::getPassRegistry(); llvm::initializeCore(*registry); llvm::initializeCodeGen(*registry); llvm::initializeLoopStrengthReducePass(*registry); llvm::initializeLowerIntrinsicsPass(*registry); llvm::initializeUnreachableBlockElimPass(*registry); llvm::Triple targetTriple(mod->getTargetTriple()); if (targetTriple.getTriple().empty()) { targetTriple.setTriple(llvm::sys::getDefaultTargetTriple()); } std::cout << "Target Triple: " << targetTriple.getTriple() << "\n"; std::string error; const llvm::Target *target = llvm::TargetRegistry::lookupTarget("", targetTriple, error); if (! target) { std::cerr << argv[0] << ": " << error; return 1; } auto optLvl = llvm::CodeGenOpt::Default; switch ('0') { // TEmporary default: std::cerr << argv[0] << ": invalid optimization level.\n"; return 1; case ' ': break; case '0': optLvl = llvm::CodeGenOpt::None; break; case '1': optLvl = llvm::CodeGenOpt::Less; break; case '2': optLvl = llvm::CodeGenOpt::Default; break; case '3': optLvl = llvm::CodeGenOpt::Aggressive; break; } // llvm::TargetOptions options; // TODO: llc line 268 std::unique_ptr<llvm::TargetMachine> targetMachine(target->createTargetMachine(targetTriple.getTriple(), llvm::sys::getHostCPUName(), "", llvm::TargetOptions(), llvm::Reloc::Default, llvm::CodeModel::Default, optLvl)); assert(targetMachine && "Could not allocate target machine!"); llvm::PassManager passmanager; llvm::TargetLibraryInfo *TLI = new llvm::TargetLibraryInfo(targetTriple); passmanager.add(TLI); if (const llvm::DataLayout *datalayout = targetMachine->getSubtargetImpl()->getDataLayout()) mod->setDataLayout(datalayout); llvm::formatted_raw_ostream ostream(out->os()); // Ask the target to add backend passes as necessary. if (targetMachine->addPassesToEmitFile(passmanager, ostream, llvm::TargetMachine::CGFT_ObjectFile)) { std::cerr << argv[0] << ": target does not support generation of this" << " file type!\n"; return 1; } passmanager.run(*mod); out->keep(); return 0; }