mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 22:02:55 +01:00
Pass imports to SemIR. (#3415)
This adds instructions so that we get printing. I may adjust the instruction format a little further to add a type, but I think the basic setup will remain. Note this builds on #3414
This commit is contained in:
@@ -68,6 +68,7 @@ cc_library(
|
||||
"//toolchain/sem_ir:builtin_kind",
|
||||
"//toolchain/sem_ir:entry_point",
|
||||
"//toolchain/sem_ir:file",
|
||||
"//toolchain/sem_ir:ids",
|
||||
"//toolchain/sem_ir:inst",
|
||||
"//toolchain/sem_ir:inst_kind",
|
||||
"@llvm-project//llvm:Support",
|
||||
|
||||
+96
-35
@@ -17,6 +17,27 @@
|
||||
namespace Carbon::Check {
|
||||
|
||||
struct UnitInfo {
|
||||
// A given import within the file, with its destination.
|
||||
struct Import {
|
||||
Parse::Tree::PackagingNames names;
|
||||
UnitInfo* unit_info;
|
||||
};
|
||||
// A file's imports corresponding to a single package, for the map.
|
||||
struct PackageImports {
|
||||
// Use the constructor so that the SmallVector is only constructed
|
||||
// as-needed.
|
||||
explicit PackageImports(Parse::Node node) : node(node) {}
|
||||
|
||||
// The first `import` directive in the file, which declared the package's
|
||||
// identifier (even if the import failed). Used for associating diagnostics
|
||||
// not specific to a single import.
|
||||
Parse::Node node;
|
||||
// Whether there's an import that failed to load.
|
||||
bool has_load_error = false;
|
||||
// The list of valid imports.
|
||||
llvm::SmallVector<Import> imports;
|
||||
};
|
||||
|
||||
explicit UnitInfo(Unit& unit)
|
||||
: unit(&unit),
|
||||
translator(unit.tokens, unit.tokens->source().filename(),
|
||||
@@ -31,8 +52,11 @@ struct UnitInfo {
|
||||
ErrorTrackingDiagnosticConsumer err_tracker;
|
||||
DiagnosticEmitter<Parse::Node> emitter;
|
||||
|
||||
// A list of outgoing imports.
|
||||
llvm::SmallVector<std::pair<Parse::Node, UnitInfo*>> imports;
|
||||
// A map of package names to outgoing imports. If the
|
||||
// import's target isn't available, the unit will be nullptr to assist with
|
||||
// name lookup. Invalid imports (for example, `import Main;`) aren't added
|
||||
// because they won't add identifiers to name lookup.
|
||||
llvm::DenseMap<IdentifierId, PackageImports> package_imports_map;
|
||||
|
||||
// The remaining number of imports which must be checked before this unit can
|
||||
// be processed.
|
||||
@@ -43,6 +67,42 @@ struct UnitInfo {
|
||||
llvm::SmallVector<UnitInfo*> incoming_imports;
|
||||
};
|
||||
|
||||
// Add imports to the root block.
|
||||
static auto AddImports(Context& context, UnitInfo& unit_info) -> void {
|
||||
for (auto& [package_id, package_imports] : unit_info.package_imports_map) {
|
||||
llvm::SmallVector<const SemIR::File*> sem_irs;
|
||||
for (auto import : package_imports.imports) {
|
||||
sem_irs.push_back(&**import.unit_info->unit->sem_ir);
|
||||
}
|
||||
context.AddPackageImports(package_imports.node, package_id, sem_irs,
|
||||
package_imports.has_load_error);
|
||||
}
|
||||
}
|
||||
|
||||
// Loops over all nodes in the tree. On some errors, this may return early,
|
||||
// for example if an unrecoverable state is encountered.
|
||||
static auto ProcessParseNodes(Context& context,
|
||||
ErrorTrackingDiagnosticConsumer& err_tracker)
|
||||
-> bool {
|
||||
for (auto parse_node : context.parse_tree().postorder()) {
|
||||
// clang warns on unhandled enum values; clang-tidy is incorrect here.
|
||||
// NOLINTNEXTLINE(bugprone-switch-missing-default-case)
|
||||
switch (auto parse_kind = context.parse_tree().node_kind(parse_node)) {
|
||||
#define CARBON_PARSE_NODE_KIND(Name) \
|
||||
case Parse::NodeKind::Name: { \
|
||||
if (!Check::Handle##Name(context, parse_node)) { \
|
||||
CARBON_CHECK(err_tracker.seen_error()) \
|
||||
<< "Handle" #Name " returned false without printing a diagnostic"; \
|
||||
return false; \
|
||||
} \
|
||||
break; \
|
||||
}
|
||||
#include "toolchain/parse/node_kind.def"
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Produces and checks the IR for the provided Parse::Tree.
|
||||
// TODO: Both valid and invalid imports should be recorded on the SemIR. Invalid
|
||||
// imports should suppress errors where it makes sense.
|
||||
@@ -54,10 +114,9 @@ static auto CheckParseTree(const SemIR::File& builtin_ir, UnitInfo& unit_info,
|
||||
|
||||
// For ease-of-access.
|
||||
SemIR::File& sem_ir = **unit_info.unit->sem_ir;
|
||||
const Parse::Tree& parse_tree = *unit_info.unit->parse_tree;
|
||||
|
||||
Check::Context context(*unit_info.unit->tokens, unit_info.emitter, parse_tree,
|
||||
sem_ir, vlog_stream);
|
||||
Context context(*unit_info.unit->tokens, unit_info.emitter,
|
||||
*unit_info.unit->parse_tree, sem_ir, vlog_stream);
|
||||
PrettyStackTraceFunction context_dumper(
|
||||
[&](llvm::raw_ostream& output) { context.PrintForStackDump(output); });
|
||||
|
||||
@@ -65,24 +124,11 @@ static auto CheckParseTree(const SemIR::File& builtin_ir, UnitInfo& unit_info,
|
||||
context.inst_block_stack().Push();
|
||||
context.PushScope();
|
||||
|
||||
// Loops over all nodes in the tree. On some errors, this may return early,
|
||||
// for example if an unrecoverable state is encountered.
|
||||
for (auto parse_node : parse_tree.postorder()) {
|
||||
// clang warns on unhandled enum values; clang-tidy is incorrect here.
|
||||
// NOLINTNEXTLINE(bugprone-switch-missing-default-case)
|
||||
switch (auto parse_kind = parse_tree.node_kind(parse_node)) {
|
||||
#define CARBON_PARSE_NODE_KIND(Name) \
|
||||
case Parse::NodeKind::Name: { \
|
||||
if (!Check::Handle##Name(context, parse_node)) { \
|
||||
CARBON_CHECK(unit_info.err_tracker.seen_error()) \
|
||||
<< "Handle" #Name " returned false without printing a diagnostic"; \
|
||||
sem_ir.set_has_errors(true); \
|
||||
return; \
|
||||
} \
|
||||
break; \
|
||||
}
|
||||
#include "toolchain/parse/node_kind.def"
|
||||
}
|
||||
AddImports(context, unit_info);
|
||||
|
||||
if (!ProcessParseNodes(context, unit_info.err_tracker)) {
|
||||
context.sem_ir().set_has_errors(true);
|
||||
return;
|
||||
}
|
||||
|
||||
// Pop information for the file-level scope.
|
||||
@@ -228,11 +274,19 @@ static auto TrackImport(
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the package imports.
|
||||
auto package_imports_it =
|
||||
unit_info.package_imports_map.try_emplace(import.package_id, import.node)
|
||||
.first;
|
||||
|
||||
if (auto api = api_map.find(import_key); api != api_map.end()) {
|
||||
unit_info.imports.push_back({import.node, api->second});
|
||||
// Add references between the file and imported api.
|
||||
package_imports_it->second.imports.push_back({import, api->second});
|
||||
++unit_info.imports_remaining;
|
||||
api->second->incoming_imports.push_back(&unit_info);
|
||||
} else {
|
||||
// The imported api is missing.
|
||||
package_imports_it->second.has_load_error = true;
|
||||
CARBON_DIAGNOSTIC(LibraryApiNotFound, Error,
|
||||
"Corresponding API not found.");
|
||||
CARBON_DIAGNOSTIC(ImportNotFound, Error, "Imported API not found.");
|
||||
@@ -392,17 +446,24 @@ auto CheckParseTrees(const SemIR::File& builtin_ir,
|
||||
// TODO: Better identify cycles, maybe try to untangle them.
|
||||
for (auto& unit_info : unit_infos) {
|
||||
if (unit_info.imports_remaining > 0) {
|
||||
for (auto* import_it = unit_info.imports.begin();
|
||||
import_it != unit_info.imports.end();) {
|
||||
auto* import_unit = import_it->second->unit;
|
||||
if (*import_unit->sem_ir) {
|
||||
++import_it;
|
||||
} else {
|
||||
CARBON_DIAGNOSTIC(ImportCycleDetected, Error,
|
||||
"Import cannot be used due to a cycle. Cycle "
|
||||
"must be fixed to import.");
|
||||
unit_info.emitter.Emit(import_it->first, ImportCycleDetected);
|
||||
import_it = unit_info.imports.erase(import_it);
|
||||
for (auto& [package_id, package_imports] :
|
||||
unit_info.package_imports_map) {
|
||||
for (auto* import_it = package_imports.imports.begin();
|
||||
import_it != package_imports.imports.end();) {
|
||||
if (*import_it->unit_info->unit->sem_ir) {
|
||||
// The import is checked, so continue.
|
||||
++import_it;
|
||||
} else {
|
||||
// The import hasn't been checked, indicating a cycle.
|
||||
CARBON_DIAGNOSTIC(ImportCycleDetected, Error,
|
||||
"Import cannot be used due to a cycle. Cycle "
|
||||
"must be fixed to import.");
|
||||
unit_info.emitter.Emit(import_it->names.node,
|
||||
ImportCycleDetected);
|
||||
// Make this look the same as an import which wasn't found.
|
||||
package_imports.has_load_error = true;
|
||||
import_it = package_imports.imports.erase(import_it);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,8 +15,10 @@
|
||||
#include "toolchain/lex/tokenized_buffer.h"
|
||||
#include "toolchain/parse/node_kind.h"
|
||||
#include "toolchain/sem_ir/file.h"
|
||||
#include "toolchain/sem_ir/ids.h"
|
||||
#include "toolchain/sem_ir/inst.h"
|
||||
#include "toolchain/sem_ir/inst_kind.h"
|
||||
#include "toolchain/sem_ir/typed_insts.h"
|
||||
|
||||
namespace Carbon::Check {
|
||||
|
||||
@@ -112,6 +114,45 @@ auto Context::NoteIncompleteClass(SemIR::ClassId class_id,
|
||||
}
|
||||
}
|
||||
|
||||
auto Context::AddPackageImports(Parse::Node import_node,
|
||||
IdentifierId package_id,
|
||||
llvm::ArrayRef<const SemIR::File*> sem_irs,
|
||||
bool has_load_error) -> void {
|
||||
CARBON_CHECK(has_load_error || !sem_irs.empty())
|
||||
<< "There should be either a load error or at least one IR.";
|
||||
|
||||
auto name_id = SemIR::NameId::ForIdentifier(package_id);
|
||||
|
||||
SemIR::CrossRefIRId first_id(cross_ref_irs().size());
|
||||
for (const auto* sem_ir : sem_irs) {
|
||||
cross_ref_irs().Add(sem_ir);
|
||||
}
|
||||
if (has_load_error) {
|
||||
cross_ref_irs().Add(nullptr);
|
||||
}
|
||||
SemIR::CrossRefIRId last_id(cross_ref_irs().size() - 1);
|
||||
|
||||
auto type_id = GetBuiltinType(SemIR::BuiltinKind::NamespaceType);
|
||||
auto inst_id = AddInst(SemIR::Import{.parse_node = import_node,
|
||||
.type_id = type_id,
|
||||
.first_cross_ref_ir_id = first_id,
|
||||
.last_cross_ref_ir_id = last_id});
|
||||
if (name_id.is_valid()) {
|
||||
// Add the import to lookup. Should always succeed because imports will be
|
||||
// uniquely named.
|
||||
AddNameToLookup(import_node, name_id, inst_id);
|
||||
// Add a name for formatted output. This isn't used in name lookup in order
|
||||
// to reduce indirection, but it's separate from the Import because it
|
||||
// otherwise fits in an Inst.
|
||||
AddInst(SemIR::BindName{.parse_node = import_node,
|
||||
.type_id = type_id,
|
||||
.name_id = name_id,
|
||||
.value_id = inst_id});
|
||||
} else {
|
||||
// TODO: All names from the current package should be added.
|
||||
}
|
||||
}
|
||||
|
||||
auto Context::AddNameToLookup(Parse::Node name_node, SemIR::NameId name_id,
|
||||
SemIR::InstId target_id) -> void {
|
||||
if (current_scope().names.insert(name_id).second) {
|
||||
@@ -811,6 +852,7 @@ class TypeCompleter {
|
||||
case SemIR::Deref::Kind:
|
||||
case SemIR::Field::Kind:
|
||||
case SemIR::FunctionDecl::Kind:
|
||||
case SemIR::Import::Kind:
|
||||
case SemIR::InitializeFrom::Kind:
|
||||
case SemIR::IntegerLiteral::Kind:
|
||||
case SemIR::NameRef::Kind:
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "toolchain/check/node_stack.h"
|
||||
#include "toolchain/parse/tree.h"
|
||||
#include "toolchain/sem_ir/file.h"
|
||||
#include "toolchain/sem_ir/ids.h"
|
||||
#include "toolchain/sem_ir/inst.h"
|
||||
|
||||
namespace Carbon::Check {
|
||||
@@ -62,6 +63,12 @@ class Context {
|
||||
// result.
|
||||
auto AddInstAndPush(Parse::Node parse_node, SemIR::Inst inst) -> void;
|
||||
|
||||
// Adds a package's imports to name lookup, with all libraries together.
|
||||
// sem_irs will all be non-null; has_load_error must be used for any errors.
|
||||
auto AddPackageImports(Parse::Node import_node, IdentifierId package_id,
|
||||
llvm::ArrayRef<const SemIR::File*> sem_irs,
|
||||
bool has_load_error) -> void;
|
||||
|
||||
// Adds a name to name lookup. Prints a diagnostic for name conflicts.
|
||||
auto AddNameToLookup(Parse::Node name_node, SemIR::NameId name_id,
|
||||
SemIR::InstId target_id) -> void;
|
||||
|
||||
@@ -39,10 +39,14 @@ import library "lib";
|
||||
// CHECK:STDOUT: file "api_lib.carbon" {
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: file "same_package.carbon" {
|
||||
// CHECK:STDOUT: %import: <namespace> = import ir1, ir2
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: file "different_package.carbon" {
|
||||
// CHECK:STDOUT: %import: <namespace> = import ir1, ir2
|
||||
// CHECK:STDOUT: %Api: <namespace> = bind_name Api, %import
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: file "main_lib_api.carbon" {
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: file "main_import.carbon" {
|
||||
// CHECK:STDOUT: %import: <namespace> = import ir1, ir1
|
||||
// CHECK:STDOUT: }
|
||||
|
||||
@@ -26,8 +26,13 @@ package Foo library "Bar" impl;
|
||||
library "Bar" impl;
|
||||
|
||||
// CHECK:STDOUT: file "no_api.impl.carbon" {
|
||||
// CHECK:STDOUT: %import: <namespace> = import ir1, ir1
|
||||
// CHECK:STDOUT: %Foo: <namespace> = bind_name Foo, %import
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: file "no_api_lib.impl.carbon" {
|
||||
// CHECK:STDOUT: %import: <namespace> = import ir1, ir1
|
||||
// CHECK:STDOUT: %Foo: <namespace> = bind_name Foo, %import
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: file "no_api_main_lib.impl.carbon" {
|
||||
// CHECK:STDOUT: %import: <namespace> = import ir1, ir1
|
||||
// CHECK:STDOUT: }
|
||||
|
||||
@@ -48,12 +48,22 @@ package CycleChild api;
|
||||
import B;
|
||||
|
||||
// CHECK:STDOUT: file "a.carbon" {
|
||||
// CHECK:STDOUT: %import: <namespace> = import ir1, ir1
|
||||
// CHECK:STDOUT: %B: <namespace> = bind_name B, %import
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: file "b.carbon" {
|
||||
// CHECK:STDOUT: %import: <namespace> = import ir1, ir1
|
||||
// CHECK:STDOUT: %C: <namespace> = bind_name C, %import
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: file "c.carbon" {
|
||||
// CHECK:STDOUT: %import: <namespace> = import ir1, ir1
|
||||
// CHECK:STDOUT: %A: <namespace> = bind_name A, %import
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: file "c.impl.carbon" {
|
||||
// CHECK:STDOUT: %import: <namespace> = import ir1, ir1
|
||||
// CHECK:STDOUT: %C: <namespace> = bind_name C, %import
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: file "cycle_child.carbon" {
|
||||
// CHECK:STDOUT: %import: <namespace> = import ir1, ir1
|
||||
// CHECK:STDOUT: %B: <namespace> = bind_name B, %import
|
||||
// CHECK:STDOUT: }
|
||||
|
||||
@@ -77,16 +77,23 @@ package SwappedExt impl;
|
||||
// CHECK:STDOUT: file "main_lib.incorrect" {
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: file "main_lib_impl.incorrect" {
|
||||
// CHECK:STDOUT: %import: <namespace> = import ir1, ir1
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: file "package.incorrect" {
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: file "package_impl.incorrect" {
|
||||
// CHECK:STDOUT: %import: <namespace> = import ir1, ir1
|
||||
// CHECK:STDOUT: %Package: <namespace> = bind_name Package, %import
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: file "package_lib.incorrect" {
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: file "package_lib_impl.incorrect" {
|
||||
// CHECK:STDOUT: %import: <namespace> = import ir1, ir1
|
||||
// CHECK:STDOUT: %Package: <namespace> = bind_name Package, %import
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: file "swapped_ext.impl.carbon" {
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: file "swapped_ext.carbon" {
|
||||
// CHECK:STDOUT: %import: <namespace> = import ir1, ir1
|
||||
// CHECK:STDOUT: %SwappedExt: <namespace> = bind_name SwappedExt, %import
|
||||
// CHECK:STDOUT: }
|
||||
|
||||
@@ -41,6 +41,8 @@ import library default;
|
||||
// CHECK:STDOUT: file "default_api.carbon" {
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: file "default.impl.carbon" {
|
||||
// CHECK:STDOUT: %import: <namespace> = import ir1, ir1
|
||||
// CHECK:STDOUT: %A: <namespace> = bind_name A, %import
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: file "main_import_default.carbon" {
|
||||
// CHECK:STDOUT: }
|
||||
|
||||
@@ -93,10 +93,16 @@ import ImportNotFound;
|
||||
// CHECK:STDOUT: file "implicit_api.carbon" {
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: file "implicit.impl.carbon" {
|
||||
// CHECK:STDOUT: %import: <namespace> = import ir1, ir1
|
||||
// CHECK:STDOUT: %Implicit: <namespace> = bind_name Implicit, %import
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: file "implicit_lib_api.carbon" {
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: file "implicit_lib.impl.carbon" {
|
||||
// CHECK:STDOUT: %import: <namespace> = import ir1, ir1
|
||||
// CHECK:STDOUT: %Implicit: <namespace> = bind_name Implicit, %import
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: file "not_found.carbon" {
|
||||
// CHECK:STDOUT: %import: <namespace> = import ir1, ir1
|
||||
// CHECK:STDOUT: %ImportNotFound: <namespace> = bind_name ImportNotFound, %import
|
||||
// CHECK:STDOUT: }
|
||||
|
||||
@@ -65,6 +65,10 @@ import library default;
|
||||
// CHECK:STDOUT: file "main_lib.carbon" {
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: file "import.carbon" {
|
||||
// CHECK:STDOUT: %import.loc2: <namespace> = import ir1, ir2
|
||||
// CHECK:STDOUT: %Api: <namespace> = bind_name Api, %import.loc2
|
||||
// CHECK:STDOUT: %import.loc20: <namespace> = import ir3, ir3
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: file "default_import.carbon" {
|
||||
// CHECK:STDOUT: %import: <namespace> = import ir1, ir1
|
||||
// CHECK:STDOUT: }
|
||||
|
||||
@@ -50,16 +50,23 @@ library "lib" impl;
|
||||
// CHECK:STDOUT: file "with_impl.carbon" {
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: file "with_impl.impl.carbon" {
|
||||
// CHECK:STDOUT: %import: <namespace> = import ir1, ir1
|
||||
// CHECK:STDOUT: %WithImpl: <namespace> = bind_name WithImpl, %import
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: file "with_impl_extra.impl.carbon" {
|
||||
// CHECK:STDOUT: %import: <namespace> = import ir1, ir1
|
||||
// CHECK:STDOUT: %WithImpl: <namespace> = bind_name WithImpl, %import
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: file "with_impl_lib.carbon" {
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: file "with_impl_lib.impl.carbon" {
|
||||
// CHECK:STDOUT: %import: <namespace> = import ir1, ir1
|
||||
// CHECK:STDOUT: %WithImpl: <namespace> = bind_name WithImpl, %import
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: file "main.carbon" {
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: file "main_lib.carbon" {
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: file "main_lib.impl.carbon" {
|
||||
// CHECK:STDOUT: %import: <namespace> = import ir1, ir1
|
||||
// CHECK:STDOUT: }
|
||||
|
||||
@@ -186,6 +186,14 @@ auto HandleFunctionDecl(FunctionContext& /*context*/, SemIR::InstId /*inst_id*/,
|
||||
<< inst;
|
||||
}
|
||||
|
||||
auto HandleImport(FunctionContext& /*context*/, SemIR::InstId /*inst_id*/,
|
||||
SemIR::Import inst) -> void {
|
||||
CARBON_FATAL()
|
||||
<< "Should not be encountered. If that changes, we may want to change "
|
||||
"higher-level logic to skip them rather than calling this. "
|
||||
<< inst;
|
||||
}
|
||||
|
||||
auto HandleInitializeFrom(FunctionContext& context, SemIR::InstId /*inst_id*/,
|
||||
SemIR::InitializeFrom inst) -> void {
|
||||
auto storage_type_id = context.sem_ir().insts().Get(inst.dest_id).type_id();
|
||||
|
||||
@@ -65,6 +65,7 @@ cc_library(
|
||||
hdrs = ["file.h"],
|
||||
deps = [
|
||||
":builtin_kind",
|
||||
":ids",
|
||||
":inst",
|
||||
":inst_kind",
|
||||
":value_stores",
|
||||
@@ -81,6 +82,7 @@ cc_library(
|
||||
hdrs = ["formatter.h"],
|
||||
deps = [
|
||||
":file",
|
||||
":ids",
|
||||
":inst_kind",
|
||||
"//toolchain/base:value_store",
|
||||
"//toolchain/lex:tokenized_buffer",
|
||||
|
||||
@@ -70,7 +70,7 @@ CARBON_SEM_IR_BUILTIN_KIND(FunctionType, "<function>")
|
||||
// The type of bound method values.
|
||||
CARBON_SEM_IR_BUILTIN_KIND(BoundMethodType, "<bound method>")
|
||||
|
||||
// The type of namespace names.
|
||||
// The type of namespace and imported package names.
|
||||
CARBON_SEM_IR_BUILTIN_KIND(NamespaceType, "<namespace>")
|
||||
|
||||
// Keep invalid last, so that we can use values as array indices without needing
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "toolchain/base/value_store.h"
|
||||
#include "toolchain/base/yaml.h"
|
||||
#include "toolchain/sem_ir/builtin_kind.h"
|
||||
#include "toolchain/sem_ir/ids.h"
|
||||
#include "toolchain/sem_ir/inst.h"
|
||||
#include "toolchain/sem_ir/inst_kind.h"
|
||||
|
||||
@@ -203,6 +204,7 @@ static auto GetTypePrecedence(InstKind kind) -> int {
|
||||
case Deref::Kind:
|
||||
case Field::Kind:
|
||||
case FunctionDecl::Kind:
|
||||
case Import::Kind:
|
||||
case InitializeFrom::Kind:
|
||||
case IntegerLiteral::Kind:
|
||||
case Namespace::Kind:
|
||||
@@ -406,6 +408,7 @@ auto File::StringifyTypeExpr(InstId outer_inst_id, bool in_type_context) const
|
||||
case Deref::Kind:
|
||||
case Field::Kind:
|
||||
case FunctionDecl::Kind:
|
||||
case Import::Kind:
|
||||
case InitializeFrom::Kind:
|
||||
case IntegerLiteral::Kind:
|
||||
case Namespace::Kind:
|
||||
@@ -473,6 +476,7 @@ auto GetExprCategory(const File& file, InstId inst_id) -> ExprCategory {
|
||||
case ClassDecl::Kind:
|
||||
case Field::Kind:
|
||||
case FunctionDecl::Kind:
|
||||
case Import::Kind:
|
||||
case Namespace::Kind:
|
||||
case NoOp::Kind:
|
||||
case Return::Kind:
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "llvm/Support/FormatVariadic.h"
|
||||
#include "toolchain/base/value_store.h"
|
||||
#include "toolchain/base/yaml.h"
|
||||
#include "toolchain/sem_ir/ids.h"
|
||||
#include "toolchain/sem_ir/inst.h"
|
||||
#include "toolchain/sem_ir/value_stores.h"
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "toolchain/base/value_store.h"
|
||||
#include "toolchain/lex/tokenized_buffer.h"
|
||||
#include "toolchain/parse/tree.h"
|
||||
#include "toolchain/sem_ir/ids.h"
|
||||
|
||||
namespace Carbon::SemIR {
|
||||
|
||||
@@ -440,6 +441,10 @@ class InstNamer {
|
||||
sem_ir_.classes().Get(inst.As<ClassType>().class_id).name_id);
|
||||
continue;
|
||||
}
|
||||
case Import::Kind: {
|
||||
add_inst_name("import");
|
||||
continue;
|
||||
}
|
||||
case NameRef::Kind: {
|
||||
add_inst_name_id(inst.As<NameRef>().name_id, ".ref");
|
||||
continue;
|
||||
@@ -494,8 +499,6 @@ class Formatter {
|
||||
FormatConstants();
|
||||
|
||||
out_ << "file \"" << sem_ir_.filename() << "\" {\n";
|
||||
// TODO: Include information from the `package` declaration, once we
|
||||
// fully support it.
|
||||
// TODO: Handle the case where there are multiple top-level instruction
|
||||
// blocks. For example, there may be branching in the initializer of a
|
||||
// global or a type expression.
|
||||
@@ -853,6 +856,8 @@ class Formatter {
|
||||
|
||||
auto FormatArg(ClassId id) -> void { FormatClassName(id); }
|
||||
|
||||
auto FormatArg(CrossRefIRId id) -> void { out_ << id; }
|
||||
|
||||
auto FormatArg(IntegerId id) -> void {
|
||||
sem_ir_.integers().Get(id).print(out_, /*isSigned=*/false);
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ CARBON_SEM_IR_INST_KIND(CrossRef)
|
||||
CARBON_SEM_IR_INST_KIND(Deref)
|
||||
CARBON_SEM_IR_INST_KIND(Field)
|
||||
CARBON_SEM_IR_INST_KIND(FunctionDecl)
|
||||
CARBON_SEM_IR_INST_KIND(Import)
|
||||
CARBON_SEM_IR_INST_KIND(InitializeFrom)
|
||||
CARBON_SEM_IR_INST_KIND(IntegerLiteral)
|
||||
CARBON_SEM_IR_INST_KIND(NameRef)
|
||||
|
||||
@@ -290,6 +290,19 @@ struct FunctionDecl {
|
||||
FunctionId function_id;
|
||||
};
|
||||
|
||||
// An import corresponds to some number of IRs. The range of imported IRs is
|
||||
// inclusive of last_cross_ref_ir_id, and will always be non-empty. If
|
||||
// there was an import error, first_cross_ref_ir_id will reference a
|
||||
// nullptr IR; there should only ever be one nullptr in the range.
|
||||
struct Import {
|
||||
static constexpr auto Kind = InstKind::Import.Define("import");
|
||||
|
||||
Parse::Node parse_node;
|
||||
TypeId type_id;
|
||||
CrossRefIRId first_cross_ref_ir_id;
|
||||
CrossRefIRId last_cross_ref_ir_id;
|
||||
};
|
||||
|
||||
// Finalizes the initialization of `dest_id` from the initializer expression
|
||||
// `src_id`, by performing a final copy from source to destination, for types
|
||||
// whose initialization is not in-place.
|
||||
|
||||
Reference in New Issue
Block a user