Repository: carbon-language/carbon-lang
File: toolchain/lower/context.cpp (C++)

Code before:
    return file_context;
  });
  return *insert_result.value();
}

auto Context::LowerPendingDefinitions() -> void {
  // Lower function definitions for generics.
  for (auto [file_context, function_id, specific_id] :
       GrowingRange(specific_function_definitions_)) {
    file_context->BuildFunctionDefinition(function_id, specific_id);
  }
}

auto Context::Finalize(
    bool run_llvm_verifier) && -> std::unique_ptr<llvm::Module> {
  LowerPendingDefinitions();

  file_contexts_.ForEach(
      [](auto, auto& file_context) { file_context->Finalize(); });

  if (run_llvm_verifier) {
    RawStringOstream errs;
    CARBON_CHECK(!llvm::verifyModule(*llvm_module_, &errs),
                 "Verifier errors (to see full IR, use `--dump-llvm-ir "
                 "--no-verify-llvm-ir`):\n{0}",
                 errs.TakeStr());
  }
  return std::move(llvm_module_);
}

auto Context::BuildDICompileUnit(llvm::StringRef module_name,
                                 llvm::Module& llvm_module,
                                 llvm::DIBuilder& di_builder)
    -> llvm::DICompileUnit* {
  llvm_module.addModuleFlag(llvm::Module::Max, "Dwarf Version", 5);
  llvm_module.addModuleFlag(llvm::Module::Warning, "Debug Info Version",
                            llvm::DEBUG_METADATA_VERSION);
  // TODO: Include directory path in the compile_unit_file.
  llvm::DIFile* compile_unit_file = di_builder.createFile(module_name, "");
  // TODO: Introduce a new language code for Carbon. C works well for now since
  // it's something debuggers will already know/have support for at least.
  // Probably have to bump to C++ at some point for virtual functions,
  // templates, etc.
  return di_builder.createCompileUnit(llvm::dwarf::DW_LANG_C, compile_unit_file,
                                      "carbon",
                                      /*isOptimized=*/false, /*Flags=*/"",
                                      /*RV=*/0);
}

auto Context::GetLocForDI(SemIR::AbsoluteNodeId abs_node_id) -> LocForDI {
  const auto& tree_and_subtrees =

Review comment (bug):
Another thing to think about in maybe a follow-up PR -- I wonder if it makes sense to directly pass a stream here rather than a string. Specifically, there have been a decent number of cases in the past where the verifier crashes due to a bug after detecting some invalid IR... It's not supposed to, of course, but it happens. When it does, having the incremental output is likely useful.

Anyways, not completely certain about this... I don't recall if there are any non-failure paths that use the stream, and maybe there are other tradeoffs here I've not thought about. But not really suggesting for this PR anyways, just an idea if there are iterations here.

Code after:
    return file_context;
  });
  return *insert_result.value();
}

auto Context::LowerPendingDefinitions() -> void {
  // Lower function definitions for generics.
  for (auto [file_context, function_id, specific_id] :
       GrowingRange(specific_function_definitions_)) {
    file_context->BuildFunctionDefinition(function_id, specific_id);
  }
}

auto Context::Finalize(
    llvm::raw_ostream*
        llvm_verifier_stream) && -> std::unique_ptr<llvm::Module> {
  LowerPendingDefinitions();

  file_contexts_.ForEach(
      [](auto, auto& file_context) { file_context->Finalize(); });

  if (llvm_verifier_stream) {
    CARBON_CHECK(!llvm::verifyModule(*llvm_module_, llvm_verifier_stream));
  }
  return std::move(llvm_module_);
}

auto Context::BuildDICompileUnit(llvm::StringRef module_name,
                                 llvm::Module& llvm_module,
                                 llvm::DIBuilder& di_builder)
    -> llvm::DICompileUnit* {
  llvm_module.addModuleFlag(llvm::Module::Max, "Dwarf Version", 5);
  llvm_module.addModuleFlag(llvm::Module::Warning, "Debug Info Version",
                            llvm::DEBUG_METADATA_VERSION);
  // TODO: Include directory path in the compile_unit_file.
  llvm::DIFile* compile_unit_file = di_builder.createFile(module_name, "");
  // TODO: Introduce a new language code for Carbon. C works well for now since
  // it's something debuggers will already know/have support for at least.
  // Probably have to bump to C++ at some point for virtual functions,
  // templates, etc.
  return di_builder.createCompileUnit(llvm::dwarf::DW_LANG_C, compile_unit_file,
                                      "carbon",
                                      /*isOptimized=*/false, /*Flags=*/"",
                                      /*RV=*/0);
}

auto Context::GetLocForDI(SemIR::AbsoluteNodeId abs_node_id) -> LocForDI {
  const auto& tree_and_subtrees =
      tree_and_subtrees_getters()[abs_node_id.check_ir_id().index]();
  const auto& tokens = tree_and_subtrees.tree().tokens();