Beispiel #1
0
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);
}
Beispiel #2
0
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;
}
Beispiel #3
0
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);
}
Beispiel #4
0
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
}
Beispiel #5
0
/// \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;
}