Bläddra i källkod

Factor library names into their own ID structure. (#4219)

This supports distinguishing between unset, Default, and "incorrect but
already diagnosed, do not use" for `extern library` logic.
Jon Ross-Perkins 1 år sedan
förälder
incheckning
64204d9182

+ 2 - 1
toolchain/check/check.cpp

@@ -883,7 +883,8 @@ static auto CheckParseTree(
     library_id = packaging->names.library_id;
   }
   unit_info.unit->sem_ir->emplace(
-      unit_info.check_ir_id, package_id, library_id,
+      unit_info.check_ir_id, package_id,
+      SemIR::LibraryNameId::ForStringLiteralValueId(library_id),
       *unit_info.unit->value_stores,
       unit_info.unit->tokens->source().filename().str());
 

+ 1 - 1
toolchain/sem_ir/file.cpp

@@ -20,7 +20,7 @@
 namespace Carbon::SemIR {
 
 File::File(CheckIRId check_ir_id, IdentifierId package_id,
-           StringLiteralValueId library_id, SharedValueStores& value_stores,
+           LibraryNameId library_id, SharedValueStores& value_stores,
            std::string filename)
     : check_ir_id_(check_ir_id),
       package_id_(package_id),

+ 4 - 4
toolchain/sem_ir/file.h

@@ -34,8 +34,8 @@ class File : public Printable<File> {
  public:
   // Starts a new file for Check::CheckParseTree.
   explicit File(CheckIRId check_ir_id, IdentifierId package_id,
-                StringLiteralValueId library_id,
-                SharedValueStores& value_stores, std::string filename);
+                LibraryNameId library_id, SharedValueStores& value_stores,
+                std::string filename);
 
   File(const File&) = delete;
   auto operator=(const File&) -> File& = delete;
@@ -82,7 +82,7 @@ class File : public Printable<File> {
 
   auto check_ir_id() const -> CheckIRId { return check_ir_id_; }
   auto package_id() const -> IdentifierId { return package_id_; }
-  auto library_id() const -> StringLiteralValueId { return library_id_; }
+  auto library_id() const -> SemIR::LibraryNameId { return library_id_; }
 
   // Directly expose SharedValueStores members.
   auto identifiers() -> CanonicalValueStore<IdentifierId>& {
@@ -181,7 +181,7 @@ class File : public Printable<File> {
   IdentifierId package_id_ = IdentifierId::Invalid;
 
   // The file's library.
-  StringLiteralValueId library_id_ = StringLiteralValueId::Invalid;
+  LibraryNameId library_id_ = LibraryNameId::Invalid;
 
   // Shared, compile-scoped values.
   SharedValueStores* value_stores_;

+ 5 - 3
toolchain/sem_ir/formatter.cpp

@@ -900,10 +900,12 @@ class FormatterImpl {
       out_ << "Main";
     }
     out_ << "//";
-    if (import_ir.library_id().is_valid()) {
-      out_ << import_ir.string_literal_values().Get(import_ir.library_id());
-    } else {
+    CARBON_CHECK(import_ir.library_id().is_valid());
+    if (import_ir.library_id() == LibraryNameId::Default) {
       out_ << "default";
+    } else {
+      out_ << import_ir.string_literal_values().Get(
+          import_ir.library_id().AsStringLiteralValueId());
     }
   }
 

+ 1 - 1
toolchain/sem_ir/id_kind.h

@@ -123,7 +123,7 @@ using IdKind = TypeEnum<
     InstId, ConstantId, EntityNameId, CompileTimeBindIndex, FunctionId, ClassId,
     InterfaceId, ImplId, GenericId, SpecificId, ImportIRId, ImportIRInstId,
     LocId, BoolValue, IntKind, NameId, NameScopeId, InstBlockId, TypeId,
-    TypeBlockId, ElementIndex, FloatKind>;
+    TypeBlockId, ElementIndex, LibraryNameId, FloatKind>;
 
 }  // namespace Carbon::SemIR
 

+ 50 - 0
toolchain/sem_ir/ids.h

@@ -695,6 +695,56 @@ struct ElementIndex : public IndexBase, public Printable<ElementIndex> {
   }
 };
 
+// The ID of a library name. This is either a string literal or `default`.
+struct LibraryNameId : public IdBase, public Printable<NameId> {
+  using DiagnosticType = DiagnosticTypeInfo<std::string>;
+
+  // An explicitly invalid ID.
+  static const LibraryNameId Invalid;
+  // The name of `default`.
+  static const LibraryNameId Default;
+  // Track cases where the library name was set, but has been diagnosed and
+  // shouldn't be used anymore.
+  static const LibraryNameId Error;
+
+  // Returns the LibraryNameId for a library name as a string literal.
+  static auto ForStringLiteralValueId(StringLiteralValueId id)
+      -> LibraryNameId {
+    CARBON_CHECK(id.index >= InvalidIndex)
+        << "Unexpected library name ID " << id;
+    if (id == StringLiteralValueId::Invalid) {
+      // Prior to SemIR, we use invalid to indicate `default`.
+      return LibraryNameId::Default;
+    } else {
+      return LibraryNameId(id.index);
+    }
+  }
+
+  using IdBase::IdBase;
+
+  // Converts a LibraryNameId back to a string literal.
+  auto AsStringLiteralValueId() const -> StringLiteralValueId {
+    CARBON_CHECK(index >= InvalidIndex) << *this << " must be handled directly";
+    return StringLiteralValueId(index);
+  }
+
+  auto Print(llvm::raw_ostream& out) const -> void {
+    out << "libraryName";
+    if (*this == Default) {
+      out << "Default";
+    } else if (*this == Error) {
+      out << "<error>";
+    } else {
+      IdBase::Print(out);
+    }
+  }
+};
+
+constexpr LibraryNameId LibraryNameId::Invalid = LibraryNameId(InvalidIndex);
+constexpr LibraryNameId LibraryNameId::Default =
+    LibraryNameId(InvalidIndex - 1);
+constexpr LibraryNameId LibraryNameId::Error = LibraryNameId(InvalidIndex - 2);
+
 // The ID of an ImportIRInst.
 struct ImportIRInstId : public IdBase, public Printable<ImportIRInstId> {
   using ValueType = ImportIRInst;