diff --git a/toolchain/driver/testdata/semantics_builtin_nodes.carbon b/toolchain/driver/testdata/semantics_builtin_nodes.carbon index dc0bcd595dee..f040121176d9 100644 --- a/toolchain/driver/testdata/semantics_builtin_nodes.carbon +++ b/toolchain/driver/testdata/semantics_builtin_nodes.carbon @@ -22,7 +22,6 @@ // CHECK:STDOUT: {kind: CrossReference, arg0: ir0, arg1: nodeFloatingPointType, type: nodeTypeType}, // CHECK:STDOUT: {kind: CrossReference, arg0: ir0, arg1: nodeStringType, type: nodeTypeType}, // CHECK:STDOUT: {kind: CrossReference, arg0: ir0, arg1: nodeEmptyTupleType, type: nodeTypeType}, -// CHECK:STDOUT: {kind: CrossReference, arg0: ir0, arg1: nodeEmptyTuple, type: nodeEmptyTupleType}, // CHECK:STDOUT: ] // CHECK:STDOUT: node_blocks: [ // CHECK:STDOUT: [ diff --git a/toolchain/lowering/lowering_context.cpp b/toolchain/lowering/lowering_context.cpp index 94eb489f2a0c..25afe50add8d 100644 --- a/toolchain/lowering/lowering_context.cpp +++ b/toolchain/lowering/lowering_context.cpp @@ -111,23 +111,11 @@ auto LoweringContext::GetLoweredNodeAsType(SemanticsNodeId node_id) auto LoweringContext::GetLoweredNodeAsValue(SemanticsNodeId node_id) -> llvm::Value* { auto& node = lowered_nodes_[node_id.index]; - if (node.is()) { - return node.get(); - } - CARBON_CHECK(node.isNull()) - << node_id << " is already set as a type, not a value"; - // Empty values are built lazily. - // TODO: It might be better to built them at initialization, putting them in - // every IR even if not used. This is probably a performance decision since it - // would simplify this function. - if (node_id == SemanticsNodeId::BuiltinEmptyTuple) { - auto* type = GetLoweredNodeAsType(SemanticsNodeId::BuiltinEmptyTupleType); - auto* value = llvm::ConstantStruct::get(llvm::cast(type), - llvm::ArrayRef()); - node = value; - return value; - } - CARBON_FATAL() << node_id << " is null, cannot be initialized"; + auto* value = node.dyn_cast(); + CARBON_CHECK(value != nullptr) + << node_id << " doesn't have a Value (either Type or null); nullness: " + << node.isNull(); + return value; } } // namespace Carbon diff --git a/toolchain/semantics/semantics_builtin_kind.cpp b/toolchain/semantics/semantics_builtin_kind.cpp index 73c8a09a5913..8ec0f80f03d8 100644 --- a/toolchain/semantics/semantics_builtin_kind.cpp +++ b/toolchain/semantics/semantics_builtin_kind.cpp @@ -14,7 +14,7 @@ CARBON_DEFINE_ENUM_CLASS_NAMES(SemanticsBuiltinKind) = { auto SemanticsBuiltinKind::label() -> llvm::StringRef { static constexpr llvm::StringLiteral Labels[] = { -#define CARBON_SEMANTICS_BUILTIN_KIND(Name, Type, Label) Label, +#define CARBON_SEMANTICS_BUILTIN_KIND(Name, Label) Label, #include "toolchain/semantics/semantics_builtin_kind.def" }; return Labels[AsInt()]; diff --git a/toolchain/semantics/semantics_builtin_kind.def b/toolchain/semantics/semantics_builtin_kind.def index 036f1c7c29fd..c283024fa6bb 100644 --- a/toolchain/semantics/semantics_builtin_kind.def +++ b/toolchain/semantics/semantics_builtin_kind.def @@ -11,9 +11,9 @@ // - CARBON_SEMANTICS_BUILTIN_KIND_NAME(Name) // Used as a fallback if other macros are missing. Used directly by Invalid // only, which is defined last. -// - CARBON_SEMANTICS_BUILTIN_KIND(Name, Type, Label) -// Defines a builtin kind with the associated type, which must also be -// builtin. +// - CARBON_SEMANTICS_BUILTIN_KIND(Name, Label) +// Defines a non-Invalid builtin type. The label is used for stringifying +// types. // // This tree represents the subset relationship between these macros, where if a // specific x-macro isn't defined, it'll fall back to the parent macro. @@ -38,12 +38,11 @@ // Tracks expressions which are valid as types. // This has a deliberately self-referential type. -CARBON_SEMANTICS_BUILTIN_KIND(TypeType, TypeType, "Type") +CARBON_SEMANTICS_BUILTIN_KIND(TypeType, "Type") // Used when a SemanticNode has an invalid type, which should then be ignored // for future type checking. -// This has a deliberately self-referential type. -CARBON_SEMANTICS_BUILTIN_KIND(InvalidType, InvalidType, "") +CARBON_SEMANTICS_BUILTIN_KIND(InvalidType, "") // ----------------------------------------------------------------------------- // TODO: Below types are all placeholders. While the above may last, the below @@ -52,19 +51,16 @@ CARBON_SEMANTICS_BUILTIN_KIND(InvalidType, InvalidType, "") // ----------------------------------------------------------------------------- // The type of integer values and integer literals, currently always i32. -CARBON_SEMANTICS_BUILTIN_KIND(IntegerType, TypeType, "i32") +CARBON_SEMANTICS_BUILTIN_KIND(IntegerType, "i32") // The type of floating point values and real literals, currently always f64. -CARBON_SEMANTICS_BUILTIN_KIND(FloatingPointType, TypeType, "f64") +CARBON_SEMANTICS_BUILTIN_KIND(FloatingPointType, "f64") // The type of string values and String literals. -CARBON_SEMANTICS_BUILTIN_KIND(StringType, TypeType, "String") +CARBON_SEMANTICS_BUILTIN_KIND(StringType, "String") // The canonical empty tuple type. -CARBON_SEMANTICS_BUILTIN_KIND(EmptyTupleType, TypeType, "() as Type") - -// The canonical empty tuple. -CARBON_SEMANTICS_BUILTIN_KIND(EmptyTuple, EmptyTupleType, "()") +CARBON_SEMANTICS_BUILTIN_KIND(EmptyTupleType, "() as Type") // Keep invalid last, so that we can use values as array indices without needing // an invalid entry. diff --git a/toolchain/semantics/semantics_context.cpp b/toolchain/semantics/semantics_context.cpp index c49066a5f38f..e85d428c9351 100644 --- a/toolchain/semantics/semantics_context.cpp +++ b/toolchain/semantics/semantics_context.cpp @@ -271,14 +271,8 @@ auto SemanticsContext::ImplicitAsImpl(SemanticsNodeId value_id, } if (as_type_id == SemanticsNodeId::BuiltinTypeType) { - // When converting `()` to a type, the result is `() as Type`. - // TODO: This might switch to be closer to the struct conversion below. - if (value_id == SemanticsNodeId::BuiltinEmptyTuple) { - if (output_value_id != nullptr) { - *output_value_id = SemanticsNodeId::BuiltinEmptyTupleType; - } - return ImplicitAsKind::Compatible; - } + // TODO: When converting `()` to a type, the result is `() as Type`. + // Right now there is no tuple value support. // When converting `{}` to a type, the result is `{} as Type`. if (value.kind() == SemanticsNodeKind::StructValue && diff --git a/toolchain/semantics/semantics_ir.cpp b/toolchain/semantics/semantics_ir.cpp index 9324ebed47de..78bae407d607 100644 --- a/toolchain/semantics/semantics_ir.cpp +++ b/toolchain/semantics/semantics_ir.cpp @@ -17,9 +17,15 @@ auto SemanticsIR::MakeBuiltinIR() -> SemanticsIR { SemanticsIR semantics(/*builtin_ir=*/nullptr); semantics.nodes_.reserve(SemanticsBuiltinKind::ValidCount); -#define CARBON_SEMANTICS_BUILTIN_KIND(Name, Type, ...) \ - semantics.nodes_.push_back(SemanticsNode::Builtin::Make( \ - SemanticsBuiltinKind::Name, SemanticsNodeId::Builtin##Type)); + // InvalidType uses a self-referential type so that it's not accidentally + // treated as a normal type. Every other builtin is a type, including the + // self-referential TypeType. +#define CARBON_SEMANTICS_BUILTIN_KIND(Name, ...) \ + semantics.nodes_.push_back(SemanticsNode::Builtin::Make( \ + SemanticsBuiltinKind::Name, \ + SemanticsBuiltinKind::Name == SemanticsBuiltinKind::InvalidType \ + ? SemanticsNodeId::BuiltinInvalidType \ + : SemanticsNodeId::BuiltinTypeType)); #include "toolchain/semantics/semantics_builtin_kind.def" CARBON_CHECK(semantics.node_blocks_.size() == 1)