mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 22:02:55 +01:00
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:
@@ -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: [
|
||||
|
||||
@@ -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()];
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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 &&
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user