void emit_file(llvm::Module &module, Internal::LLVMOStream& out, llvm::TargetMachine::CodeGenFileType file_type) { Internal::debug(1) << "emit_file.Compiling to native code...\n"; Internal::debug(2) << "Target triple: " << module.getTargetTriple() << "\n"; // Get the target specific parser. auto target_machine = Internal::make_target_machine(module); internal_assert(target_machine.get()) << "Could not allocate target machine!\n"; #if LLVM_VERSION == 37 llvm::DataLayout target_data_layout(*(target_machine->getDataLayout())); #else llvm::DataLayout target_data_layout(target_machine->createDataLayout()); #endif if (!(target_data_layout == module.getDataLayout())) { internal_error << "Warning: module's data layout does not match target machine's\n" << target_data_layout.getStringRepresentation() << "\n" << module.getDataLayout().getStringRepresentation() << "\n"; } // Build up all of the passes that we want to do to the module. llvm::legacy::PassManager pass_manager; pass_manager.add(new llvm::TargetLibraryInfoWrapperPass(llvm::Triple(module.getTargetTriple()))); // Make sure things marked as always-inline get inlined #if LLVM_VERSION < 40 pass_manager.add(llvm::createAlwaysInlinerPass()); #else pass_manager.add(llvm::createAlwaysInlinerLegacyPass()); #endif // Enable symbol rewriting. This allows code outside libHalide to // use symbol rewriting when compiling Halide code (for example, by // using cl::ParseCommandLineOption and then passing the appropriate // rewrite options via -mllvm flags). pass_manager.add(llvm::createRewriteSymbolsPass()); // Override default to generate verbose assembly. target_machine->Options.MCOptions.AsmVerbose = true; // Ask the target to add backend passes as necessary. target_machine->addPassesToEmitFile(pass_manager, out, file_type); pass_manager.run(module); }
static std::unique_ptr<llvm::tool_output_file> Compile(char const *ProgramName, llvm::Module &Module, llvm::SmallString<256> &TempObjPath) { auto Triple = llvm::Triple(Module.getTargetTriple()); if (Triple.getTriple().empty()) Triple.setTriple(llvm::sys::getDefaultTargetTriple()); std::string ErrorMessage; auto const Target = llvm::TargetRegistry::lookupTarget(Triple.getTriple(), ErrorMessage); if (!Target) { llvm::errs() << ProgramName << ": " << ErrorMessage << "\n"; exit(EXIT_FAILURE); } // Target machine options. llvm::TargetOptions Options; std::unique_ptr<llvm::TargetMachine> Machine { Target->createTargetMachine(Triple.getTriple(), /* cpu */ std::string{}, /* features */ std::string{}, Options, Optional<Reloc::Model>{}, llvm::CodeModel::Default, llvm::CodeGenOpt::Default) }; assert(Machine && "Could not allocate target machine!"); // Get an output file for the object. auto Out = GetTemporaryObjectStream(ProgramName, TempObjPath); // Setup all of the passes for the codegen. llvm::legacy::PassManager Passes; llvm::TargetLibraryInfoImpl TLII(Triple); Passes.add(new llvm::TargetLibraryInfoWrapperPass(TLII)); llvm::raw_pwrite_stream *FOS(&Out->os()); if (Machine->addPassesToEmitFile(Passes, *FOS, llvm::TargetMachine::CGFT_ObjectFile)) { llvm::errs() << ProgramName << ": can't generate object file!\n"; exit(EXIT_FAILURE); } Passes.run(Module); return Out; }
void emit_file_legacy(llvm::Module &module, Internal::LLVMOStream& out, llvm::TargetMachine::CodeGenFileType file_type) { Internal::debug(1) << "emit_file_legacy.Compiling to native code...\n"; Internal::debug(2) << "Target triple: " << module.getTargetTriple() << "\n"; // Get the target specific parser. auto target_machine = Internal::make_target_machine(module); internal_assert(target_machine.get()) << "Could not allocate target machine!\n"; // Build up all of the passes that we want to do to the module. llvm::PassManager pass_manager; // Add an appropriate TargetLibraryInfo pass for the module's triple. pass_manager.add(new llvm::TargetLibraryInfo(llvm::Triple(module.getTargetTriple()))); #if LLVM_VERSION < 33 pass_manager.add(new llvm::TargetTransformInfo(target_machine->getScalarTargetTransformInfo(), target_machine->getVectorTargetTransformInfo())); #else target_machine->addAnalysisPasses(pass_manager); #endif #if LLVM_VERSION < 35 llvm::DataLayout *layout = new llvm::DataLayout(module.get()); Internal::debug(2) << "Data layout: " << layout->getStringRepresentation(); pass_manager.add(layout); #endif // Make sure things marked as always-inline get inlined pass_manager.add(llvm::createAlwaysInlinerPass()); // Override default to generate verbose assembly. target_machine->setAsmVerbosityDefault(true); std::unique_ptr<llvm::formatted_raw_ostream> formatted_out(new llvm::formatted_raw_ostream(out)); // Ask the target to add backend passes as necessary. target_machine->addPassesToEmitFile(pass_manager, *formatted_out, file_type); pass_manager.run(module); }
void emit_file(llvm::Module &module, Internal::LLVMOStream& out, llvm::TargetMachine::CodeGenFileType file_type) { #if LLVM_VERSION < 37 emit_file_legacy(module, out, file_type); #else Internal::debug(1) << "emit_file.Compiling to native code...\n"; Internal::debug(2) << "Target triple: " << module.getTargetTriple() << "\n"; // Get the target specific parser. auto target_machine = Internal::make_target_machine(module); internal_assert(target_machine.get()) << "Could not allocate target machine!\n"; #if LLVM_VERSION == 37 llvm::DataLayout target_data_layout(*(target_machine->getDataLayout())); #else llvm::DataLayout target_data_layout(target_machine->createDataLayout()); #endif if (!(target_data_layout == module.getDataLayout())) { internal_error << "Warning: module's data layout does not match target machine's\n" << target_data_layout.getStringRepresentation() << "\n" << module.getDataLayout().getStringRepresentation() << "\n"; } // Build up all of the passes that we want to do to the module. llvm::legacy::PassManager pass_manager; pass_manager.add(new llvm::TargetLibraryInfoWrapperPass(llvm::Triple(module.getTargetTriple()))); // Make sure things marked as always-inline get inlined pass_manager.add(llvm::createAlwaysInlinerPass()); // Override default to generate verbose assembly. target_machine->Options.MCOptions.AsmVerbose = true; // Ask the target to add backend passes as necessary. target_machine->addPassesToEmitFile(pass_manager, out, file_type); pass_manager.run(module); #endif }
/// \brief Add SeeC's instrumentation to the given Module. /// \return true if the instrumentation was successful. /// static bool Instrument(char const *ProgramName, llvm::Module &Module) { llvm::legacy::PassManager Passes; // Add an appropriate TargetLibraryInfo pass for the module's triple. auto Triple = llvm::Triple(Module.getTargetTriple()); if (Triple.getTriple().empty()) Triple.setTriple(llvm::sys::getDefaultTargetTriple()); llvm::TargetLibraryInfoImpl TLII(Triple); Passes.add(new llvm::TargetLibraryInfoWrapperPass(TLII)); // Determine the path to SeeC's resource directory: // This just needs to be some symbol in the binary; C++ doesn't // allow taking the address of ::main however. void *P = (void*) (intptr_t) Instrument; auto const Path = llvm::sys::fs::getMainExecutable(ProgramName, P); auto const ResourcePath = seec::getResourceDirectory(Path); // Add SeeC's recording instrumentation pass auto const Pass = new llvm::InsertExternalRecording(ResourcePath); Passes.add(Pass); // Verify the final module Passes.add(llvm::createVerifierPass()); // Run the passes Passes.run(Module); // Check if there were unhandled external functions. for (auto Fn : Pass->getUnhandledFunctions()) { llvm::errs() << ProgramName << ": function \"" << Fn->getName() << "\" is not handled. If this function modifies memory state," " then SeeC will not be aware of it.\n"; } if (auto const Path = std::getenv("SEEC_WRITE_INSTRUMENTED")) { std::error_code EC; raw_fd_ostream Out(Path, EC, llvm::sys::fs::OpenFlags::F_Excl); if (!EC) Out << Module; else llvm::errs() << ProgramName << ": couldn't write to " << Path << ": " << EC.message() << "\n"; } return true; }