Remove the builtin empty tuple value (not type). (#2850)

We do use the empty tuple type for function returns, so I don't want to get rid of it, but the value is unused. With this change, builtins are all types. Long-term the empty tuple value should have a representation similar to structs; just a tuple value that's empty, not a built-in.
This commit is contained in:
Jon Ross-Perkins
2023-05-26 11:07:35 -07:00
committed by GitHub
parent 76151d1fff
commit 709412ca97
6 changed files with 26 additions and 43 deletions
@@ -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: [
+5 -17
View File
@@ -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<llvm::Value*>()) {
return node.get<llvm::Value*>();
}
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<llvm::StructType>(type),
llvm::ArrayRef<llvm::Constant*>());
node = value;
return value;
}
CARBON_FATAL() << node_id << " is null, cannot be initialized";
auto* value = node.dyn_cast<llvm::Value*>();
CARBON_CHECK(value != nullptr)
<< node_id << " doesn't have a Value (either Type or null); nullness: "
<< node.isNull();
return value;
}
} // namespace Carbon
@@ -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()];
+9 -13
View File
@@ -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, "<unknown>")
CARBON_SEMANTICS_BUILTIN_KIND(InvalidType, "<unknown>")
// -----------------------------------------------------------------------------
// TODO: Below types are all placeholders. While the above may last, the below
@@ -52,19 +51,16 @@ CARBON_SEMANTICS_BUILTIN_KIND(InvalidType, InvalidType, "<unknown>")
// -----------------------------------------------------------------------------
// 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.
+2 -8
View File
@@ -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 &&
+9 -3
View File
@@ -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)