codegen.cpp 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. // Part of the Carbon Language project, under the Apache License v2.0 with LLVM
  2. // Exceptions. See /LICENSE for license information.
  3. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. #include "toolchain/codegen/codegen.h"
  5. #include <cstdio>
  6. #include <memory>
  7. #include "llvm/IR/LegacyPassManager.h"
  8. #include "llvm/MC/TargetRegistry.h"
  9. #include "llvm/Support/TargetSelect.h"
  10. #include "llvm/Target/TargetOptions.h"
  11. #include "llvm/TargetParser/Host.h"
  12. namespace Carbon {
  13. auto CodeGen::CreateTargetMachine() -> std::unique_ptr<llvm::TargetMachine> {
  14. // Initialize the target registry etc.
  15. llvm::InitializeAllTargetInfos();
  16. llvm::InitializeAllTargets();
  17. llvm::InitializeAllTargetMCs();
  18. llvm::InitializeAllAsmParsers();
  19. llvm::InitializeAllAsmPrinters();
  20. std::string error;
  21. llvm::StringRef triple = target_triple;
  22. std::string host_triple;
  23. if (target_triple.empty()) {
  24. host_triple = llvm::sys::getDefaultTargetTriple();
  25. triple = host_triple;
  26. }
  27. const auto* target = llvm::TargetRegistry::lookupTarget(triple, error);
  28. if (!target) {
  29. error_stream_ << "ERROR: Invalid -target_triple: " << error << "\n";
  30. return nullptr;
  31. }
  32. constexpr llvm::StringLiteral CPU = "generic";
  33. constexpr llvm::StringLiteral Features = "";
  34. llvm::TargetOptions target_opts;
  35. std::optional<llvm::Reloc::Model> reloc_model;
  36. std::unique_ptr<llvm::TargetMachine> target_machine(
  37. target->createTargetMachine(target_triple, CPU, Features, target_opts,
  38. reloc_model));
  39. return target_machine;
  40. }
  41. auto CodeGen::EmitCode(llvm::raw_pwrite_stream& dest,
  42. llvm::TargetMachine* target_machine,
  43. llvm::CodeGenFileType file_type) -> bool {
  44. Module.setDataLayout(target_machine->createDataLayout());
  45. Module.setTargetTriple(target_triple);
  46. // Using the legacy PM to generate the assembly since the new PM
  47. // does not work with this yet.
  48. // TODO: make the new PM work with the codegen pipeline.
  49. llvm::legacy::PassManager pass;
  50. if (target_machine->addPassesToEmitFile(pass, dest, nullptr, file_type)) {
  51. error_stream_ << "Error: Nothing to write to object file\n";
  52. return false;
  53. }
  54. pass.run(Module);
  55. return true;
  56. }
  57. auto CodeGen::PrintAssembly() -> bool {
  58. auto target_machine = CreateTargetMachine();
  59. if (target_machine == nullptr) {
  60. return false;
  61. }
  62. return EmitCode(output_stream_, target_machine.get(),
  63. llvm::CodeGenFileType::CGFT_AssemblyFile);
  64. }
  65. auto CodeGen::GenerateObjectCode() -> bool {
  66. auto target_machine = CreateTargetMachine();
  67. if (target_machine == nullptr) {
  68. return false;
  69. }
  70. return EmitCode(output_stream_, target_machine.get(),
  71. llvm::CodeGenFileType::CGFT_ObjectFile);
  72. }
  73. } // namespace Carbon