Quellcode durchsuchen

Change the builtin enum approach to enforce addition. (#2584)

It feels like every time I add a builtin, I forget to add it to the builtin IR. This approach enforces the addition of builtin nodes, and also takes advantage of the normalized structure to set types appropriately (I think the new approach is simpler on this aspect).
Jon Ross-Perkins vor 3 Jahren
Ursprung
Commit
b2c60b4f53

+ 2 - 1
toolchain/semantics/semantics_builtin_kind.cpp

@@ -7,7 +7,8 @@
 namespace Carbon {
 namespace Carbon {
 
 
 CARBON_DEFINE_ENUM_CLASS_NAMES(SemanticsBuiltinKind) = {
 CARBON_DEFINE_ENUM_CLASS_NAMES(SemanticsBuiltinKind) = {
-#define CARBON_SEMANTICS_BUILTIN_KIND(Name) CARBON_ENUM_CLASS_NAME_STRING(Name)
+#define CARBON_SEMANTICS_BUILTIN_KIND_NAME(Name) \
+  CARBON_ENUM_CLASS_NAME_STRING(Name)
 #include "toolchain/semantics/semantics_builtin_kind.def"
 #include "toolchain/semantics/semantics_builtin_kind.def"
 };
 };
 
 

+ 34 - 8
toolchain/semantics/semantics_builtin_kind.def

@@ -6,30 +6,56 @@
 //
 //
 // It does not use `#include` guards, and instead is designed to be `#include`ed
 // It does not use `#include` guards, and instead is designed to be `#include`ed
 // after the x-macro is defined in order for its inclusion to expand to the
 // after the x-macro is defined in order for its inclusion to expand to the
-// desired output. The x-macro for this header is `CARBON_PARSE_NODE_KIND`. The
-// definition provided will be removed at the end of this file to clean up.
+// desired output.
+//
+// x-macros come in two forms:
+//   CARBON_SEMANTICS_BUILTIN_KIND_NAME(Name)
+//     Used as a fallback if other macros are missing.
+//   CARBON_SEMANTICS_BUILTIN_KIND(Name, Type)
+//     Defines a builtin kind with the associated type, which must also be
+//     builtin.
+//
+// Note that Invalid is provided with CARBON_SEMANTICS_BUILTIN_KIND_NAME but not
+// CARBON_SEMANTICS_BUILTIN_KIND.
+
+#if !(defined(CARBON_SEMANTICS_BUILTIN_KIND_NAME) || \
+      defined(CARBON_SEMANTICS_BUILTIN_KIND))
+#error \
+    "Must define CARBON_SEMANTICS_BUILTIN_KIND family x-macros to use this file."
+#endif
+
+// If CARBON_SEMANTICS_BUILTIN_KIND_NAME is undefined, ignore calls.
+#ifndef CARBON_SEMANTICS_BUILTIN_KIND_NAME
+#define CARBON_SEMANTICS_BUILTIN_KIND_NAME(Name)
+#endif
 
 
+// If CARBON_SEMANTICS_BUILTIN_KIND is undefined, delegate calls to
+// CARBON_SEMANTICS_BUILTIN_KIND_NAME.
 #ifndef CARBON_SEMANTICS_BUILTIN_KIND
 #ifndef CARBON_SEMANTICS_BUILTIN_KIND
-#error "Must define the x-macro to use this file."
+#define CARBON_SEMANTICS_BUILTIN_KIND(Name, ...) \
+  CARBON_SEMANTICS_BUILTIN_KIND_NAME(Name)
 #endif
 #endif
 
 
 // Tracks expressions which are valid as types.
 // Tracks expressions which are valid as types.
-CARBON_SEMANTICS_BUILTIN_KIND(TypeType)
+// This has a deliberately self-referential type.
+CARBON_SEMANTICS_BUILTIN_KIND(TypeType, TypeType)
 
 
 // Used when a SemanticNode has an invalid type, which should then be ignored
 // Used when a SemanticNode has an invalid type, which should then be ignored
 // for future type checking.
 // for future type checking.
-CARBON_SEMANTICS_BUILTIN_KIND(InvalidType)
+// This has a deliberately self-referential type.
+CARBON_SEMANTICS_BUILTIN_KIND(InvalidType, InvalidType)
 
 
 // The type of integers and integer literals, currently always i32. Long-term
 // The type of integers and integer literals, currently always i32. Long-term
 // we may not want it this way, but for now this is the approach.
 // we may not want it this way, but for now this is the approach.
-CARBON_SEMANTICS_BUILTIN_KIND(IntegerType)
+CARBON_SEMANTICS_BUILTIN_KIND(IntegerType, TypeType)
 
 
 // The type of reals and real literals, currently always f64. Long-term
 // The type of reals and real literals, currently always f64. Long-term
 // we may not want it this way, but for now this is the approach.
 // we may not want it this way, but for now this is the approach.
-CARBON_SEMANTICS_BUILTIN_KIND(RealType)
+CARBON_SEMANTICS_BUILTIN_KIND(RealType, TypeType)
 
 
 // Keep invalid last, so that we can use values as array indices without needing
 // Keep invalid last, so that we can use values as array indices without needing
 // an invalid entry.
 // an invalid entry.
-CARBON_SEMANTICS_BUILTIN_KIND(Invalid)
+CARBON_SEMANTICS_BUILTIN_KIND_NAME(Invalid)
 
 
+#undef CARBON_SEMANTICS_BUILTIN_KIND_NAME
 #undef CARBON_SEMANTICS_BUILTIN_KIND
 #undef CARBON_SEMANTICS_BUILTIN_KIND

+ 4 - 3
toolchain/semantics/semantics_builtin_kind.h

@@ -12,13 +12,14 @@
 namespace Carbon {
 namespace Carbon {
 
 
 CARBON_DEFINE_RAW_ENUM_CLASS(SemanticsBuiltinKind, uint8_t) {
 CARBON_DEFINE_RAW_ENUM_CLASS(SemanticsBuiltinKind, uint8_t) {
-#define CARBON_SEMANTICS_BUILTIN_KIND(Name) CARBON_RAW_ENUM_ENUMERATOR(Name)
+#define CARBON_SEMANTICS_BUILTIN_KIND_NAME(Name) \
+  CARBON_RAW_ENUM_ENUMERATOR(Name)
 #include "toolchain/semantics/semantics_builtin_kind.def"
 #include "toolchain/semantics/semantics_builtin_kind.def"
 };
 };
 
 
 class SemanticsBuiltinKind : public CARBON_ENUM_BASE(SemanticsBuiltinKind) {
 class SemanticsBuiltinKind : public CARBON_ENUM_BASE(SemanticsBuiltinKind) {
  public:
  public:
-#define CARBON_SEMANTICS_BUILTIN_KIND(Name) \
+#define CARBON_SEMANTICS_BUILTIN_KIND_NAME(Name) \
   CARBON_ENUM_CONSTANT_DECLARATION(Name)
   CARBON_ENUM_CONSTANT_DECLARATION(Name)
 #include "toolchain/semantics/semantics_builtin_kind.def"
 #include "toolchain/semantics/semantics_builtin_kind.def"
 
 
@@ -34,7 +35,7 @@ class SemanticsBuiltinKind : public CARBON_ENUM_BASE(SemanticsBuiltinKind) {
   using EnumBase::FromInt;
   using EnumBase::FromInt;
 };
 };
 
 
-#define CARBON_SEMANTICS_BUILTIN_KIND(Name) \
+#define CARBON_SEMANTICS_BUILTIN_KIND_NAME(Name) \
   CARBON_ENUM_CONSTANT_DEFINITION(SemanticsBuiltinKind, Name)
   CARBON_ENUM_CONSTANT_DEFINITION(SemanticsBuiltinKind, Name)
 #include "toolchain/semantics/semantics_builtin_kind.def"
 #include "toolchain/semantics/semantics_builtin_kind.def"
 
 

+ 10 - 24
toolchain/semantics/semantics_ir.cpp

@@ -14,33 +14,19 @@ namespace Carbon {
 
 
 auto SemanticsIR::MakeBuiltinIR() -> SemanticsIR {
 auto SemanticsIR::MakeBuiltinIR() -> SemanticsIR {
   SemanticsIR semantics(/*builtin_ir=*/nullptr);
   SemanticsIR semantics(/*builtin_ir=*/nullptr);
-  auto block_id = semantics.AddNodeBlock();
   semantics.nodes_.reserve(SemanticsBuiltinKind::ValidCount);
   semantics.nodes_.reserve(SemanticsBuiltinKind::ValidCount);
 
 
-  constexpr int32_t TypeOfTypeType = 0;
-  auto type_type = semantics.AddNode(
-      block_id, SemanticsNode::MakeBuiltin(SemanticsBuiltinKind::TypeType,
-                                           SemanticsNodeId(TypeOfTypeType)));
-  CARBON_CHECK(type_type.index == TypeOfTypeType)
-      << "TypeType's type must be self-referential.";
-
-  constexpr int32_t TypeOfInvalidType = 1;
-  auto invalid_type = semantics.AddNode(
-      block_id, SemanticsNode::MakeBuiltin(SemanticsBuiltinKind::InvalidType,
-                                           SemanticsNodeId(TypeOfInvalidType)));
-  CARBON_CHECK(invalid_type.index == TypeOfInvalidType)
-      << "InvalidType's type must be self-referential.";
-
-  semantics.AddNode(
-      block_id,
-      SemanticsNode::MakeBuiltin(SemanticsBuiltinKind::IntegerType, type_type));
-
-  semantics.AddNode(block_id, SemanticsNode::MakeBuiltin(
-                                  SemanticsBuiltinKind::RealType, type_type));
-
-  CARBON_CHECK(semantics.node_blocks_.size() == 2)
-      << "BuildBuiltins should produce 2 blocks, actual: "
+#define CARBON_SEMANTICS_BUILTIN_KIND(Name, Type)        \
+  semantics.nodes_.push_back(SemanticsNode::MakeBuiltin( \
+      SemanticsBuiltinKind::Name, SemanticsNodeId::Builtin##Type));
+#include "toolchain/semantics/semantics_builtin_kind.def"
+
+  CARBON_CHECK(semantics.node_blocks_.size() == 1)
+      << "BuildBuiltins should only have the empty block, actual: "
       << semantics.node_blocks_.size();
       << semantics.node_blocks_.size();
+  CARBON_CHECK(semantics.nodes_.size() == SemanticsBuiltinKind::ValidCount)
+      << "BuildBuiltins should produce " << SemanticsBuiltinKind::ValidCount
+      << " nodes, actual: " << semantics.nodes_.size();
   return semantics;
   return semantics;
 }
 }
 
 

+ 2 - 2
toolchain/semantics/semantics_node.h

@@ -22,7 +22,7 @@ struct SemanticsNodeId : public IndexBase {
   static const SemanticsNodeId Invalid;
   static const SemanticsNodeId Invalid;
 
 
 // Builtin node IDs.
 // Builtin node IDs.
-#define CARBON_SEMANTICS_BUILTIN_KIND(Name) \
+#define CARBON_SEMANTICS_BUILTIN_KIND_NAME(Name) \
   static const SemanticsNodeId Builtin##Name;
   static const SemanticsNodeId Builtin##Name;
 #include "toolchain/semantics/semantics_builtin_kind.def"
 #include "toolchain/semantics/semantics_builtin_kind.def"
 
 
@@ -37,7 +37,7 @@ constexpr SemanticsNodeId SemanticsNodeId::Invalid = SemanticsNodeId();
 
 
 // Uses the cross-reference node ID for a builtin. This relies on SemanticsIR
 // Uses the cross-reference node ID for a builtin. This relies on SemanticsIR
 // guarantees for builtin cross-reference placement.
 // guarantees for builtin cross-reference placement.
-#define CARBON_SEMANTICS_BUILTIN_KIND(Name)                  \
+#define CARBON_SEMANTICS_BUILTIN_KIND_NAME(Name)             \
   constexpr SemanticsNodeId SemanticsNodeId::Builtin##Name = \
   constexpr SemanticsNodeId SemanticsNodeId::Builtin##Name = \
       SemanticsNodeId(SemanticsBuiltinKind::Name.AsInt());
       SemanticsNodeId(SemanticsBuiltinKind::Name.AsInt());
 #include "toolchain/semantics/semantics_builtin_kind.def"
 #include "toolchain/semantics/semantics_builtin_kind.def"