mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 22:02:23 +01:00
By moving dumping, we can have dumping occur before verification that might CHECK-fail (e.g. parse tree and llvm IR verification). I'm dropping vlogging of raw semir. It was only done when dumping, so `-v` would print zero copies and `-v --dump-raw-sem-ir` would print two copies. The lack of complaints about this suggests it's not needed. I'm making a small change to drop newlines between textual and raw semir. This is an edge case so I don't expect people to really notice in general, but it seemed unusually aware of what's on a stream, and it made it harder to do the dump_stream/raw_dump_stream approach, which I felt would be decent in general, since check is the only phase that can emit two different things (which I could also just drop -- we don't really use raw semir anymore, it doesn't seem like a big need to be able to print it with textual semir, but I'm assuming to just maintain existing behavior). In parse, we were previously dumping the tree on verification errors. I'm removing that because now `--dump-parse-tree` should work fine, where previously it wouldn't.
100 lines
3.8 KiB
C++
100 lines
3.8 KiB
C++
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
|
// Exceptions. See /LICENSE for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
|
#include "toolchain/lower/context.h"
|
|
|
|
#include "common/check.h"
|
|
#include "common/growing_range.h"
|
|
#include "common/raw_string_ostream.h"
|
|
#include "common/vlog.h"
|
|
#include "llvm/Transforms/Utils/ModuleUtils.h"
|
|
#include "toolchain/lower/file_context.h"
|
|
#include "toolchain/sem_ir/inst_namer.h"
|
|
|
|
namespace Carbon::Lower {
|
|
|
|
Context::Context(
|
|
llvm::LLVMContext& llvm_context,
|
|
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> fs, bool want_debug_info,
|
|
llvm::ArrayRef<Parse::GetTreeAndSubtreesFn> tree_and_subtrees_getters,
|
|
llvm::StringRef module_name, llvm::raw_ostream* vlog_stream)
|
|
: llvm_context_(&llvm_context),
|
|
llvm_module_(std::make_unique<llvm::Module>(module_name, llvm_context)),
|
|
file_system_(std::move(fs)),
|
|
di_builder_(*llvm_module_),
|
|
di_compile_unit_(
|
|
want_debug_info
|
|
? BuildDICompileUnit(module_name, *llvm_module_, di_builder_)
|
|
: nullptr),
|
|
tree_and_subtrees_getters_(tree_and_subtrees_getters),
|
|
vlog_stream_(vlog_stream) {}
|
|
|
|
auto Context::GetFileContext(const SemIR::File* file,
|
|
const SemIR::InstNamer* inst_namer)
|
|
-> FileContext& {
|
|
auto insert_result = file_contexts_.Insert(file->check_ir_id(), [&] {
|
|
auto file_context =
|
|
std::make_unique<FileContext>(*this, *file, inst_namer, vlog_stream_);
|
|
file_context->PrepareToLower();
|
|
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() && -> std::unique_ptr<llvm::Module> {
|
|
LowerPendingDefinitions();
|
|
|
|
file_contexts_.ForEach(
|
|
[](auto, auto& file_context) { file_context->Finalize(); });
|
|
|
|
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();
|
|
|
|
if (abs_node_id.node_id().has_value()) {
|
|
auto token =
|
|
tree_and_subtrees.GetSubtreeTokenRange(abs_node_id.node_id()).begin;
|
|
return {.filename = tokens.source().filename(),
|
|
.line_number = tokens.GetLineNumber(token),
|
|
.column_number = tokens.GetColumnNumber(token)};
|
|
} else {
|
|
return {.filename = tokens.source().filename(),
|
|
.line_number = 0,
|
|
.column_number = 0};
|
|
}
|
|
}
|
|
|
|
} // namespace Carbon::Lower
|