context.cpp 3.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  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/lower/context.h"
  5. #include "common/check.h"
  6. #include "common/vlog.h"
  7. #include "llvm/Transforms/Utils/ModuleUtils.h"
  8. #include "toolchain/lower/file_context.h"
  9. #include "toolchain/sem_ir/inst_namer.h"
  10. namespace Carbon::Lower {
  11. Context::Context(llvm::LLVMContext& llvm_context,
  12. llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> fs,
  13. std::optional<llvm::ArrayRef<Parse::GetTreeAndSubtreesFn>>
  14. tree_and_subtrees_getters_for_debug_info,
  15. llvm::StringRef module_name, llvm::raw_ostream* vlog_stream)
  16. : llvm_context_(&llvm_context),
  17. llvm_module_(std::make_unique<llvm::Module>(module_name, llvm_context)),
  18. file_system_(std::move(fs)),
  19. di_builder_(*llvm_module_),
  20. di_compile_unit_(
  21. tree_and_subtrees_getters_for_debug_info
  22. ? BuildDICompileUnit(module_name, *llvm_module_, di_builder_)
  23. : nullptr),
  24. tree_and_subtrees_getters_for_debug_info_(
  25. tree_and_subtrees_getters_for_debug_info),
  26. vlog_stream_(vlog_stream) {}
  27. auto Context::GetFileContext(const SemIR::File* file,
  28. const SemIR::InstNamer* inst_namer)
  29. -> FileContext& {
  30. auto insert_result = file_contexts_.Insert(file->check_ir_id(), [&] {
  31. auto file_context =
  32. std::make_unique<FileContext>(*this, *file, inst_namer, vlog_stream_);
  33. file_context->PrepareToLower();
  34. return file_context;
  35. });
  36. return *insert_result.value();
  37. }
  38. auto Context::Finalize() && -> std::unique_ptr<llvm::Module> {
  39. file_contexts_.ForEach(
  40. [](auto, auto& file_context) { file_context->Finalize(); });
  41. return std::move(llvm_module_);
  42. }
  43. auto Context::BuildDICompileUnit(llvm::StringRef module_name,
  44. llvm::Module& llvm_module,
  45. llvm::DIBuilder& di_builder)
  46. -> llvm::DICompileUnit* {
  47. llvm_module.addModuleFlag(llvm::Module::Max, "Dwarf Version", 5);
  48. llvm_module.addModuleFlag(llvm::Module::Warning, "Debug Info Version",
  49. llvm::DEBUG_METADATA_VERSION);
  50. // TODO: Include directory path in the compile_unit_file.
  51. llvm::DIFile* compile_unit_file = di_builder.createFile(module_name, "");
  52. // TODO: Introduce a new language code for Carbon. C works well for now since
  53. // it's something debuggers will already know/have support for at least.
  54. // Probably have to bump to C++ at some point for virtual functions,
  55. // templates, etc.
  56. return di_builder.createCompileUnit(llvm::dwarf::DW_LANG_C, compile_unit_file,
  57. "carbon",
  58. /*isOptimized=*/false, /*Flags=*/"",
  59. /*RV=*/0);
  60. }
  61. auto Context::GetLocForDI(SemIR::AbsoluteNodeId abs_node_id) -> LocForDI {
  62. const auto& tree_and_subtrees =
  63. (*tree_and_subtrees_getters_for_debug_info_)[abs_node_id.check_ir_id()
  64. .index]();
  65. const auto& tokens = tree_and_subtrees.tree().tokens();
  66. if (abs_node_id.node_id().has_value()) {
  67. auto token =
  68. tree_and_subtrees.GetSubtreeTokenRange(abs_node_id.node_id()).begin;
  69. return {.filename = tokens.source().filename(),
  70. .line_number = tokens.GetLineNumber(token),
  71. .column_number = tokens.GetColumnNumber(token)};
  72. } else {
  73. return {.filename = tokens.source().filename(),
  74. .line_number = 0,
  75. .column_number = 0};
  76. }
  77. }
  78. } // namespace Carbon::Lower