[Object][Wasm] Allow parsing of GC types in type and table sections (#79235)

This change allows a WasmObjectFile to be created from a wasm file even
if it uses typed funcrefs and GC types. It does not significantly change how
lib/Object models its various internal types (e.g. WasmSignature,
WasmElemSegment), so LLVM does not really "support" or understand such
files, but it is sufficient to parse the type, global and element sections, discarding
types that are not understood. This is useful for low-level binary tools such as
nm and objcopy, which use only limited aspects of the binary (such as function
definitions) or deal with sections as opaque blobs.

This is done by allowing `WasmValType` to have a value of `OTHERREF`
(representing any unmodeled reference type), and adding a field to
`WasmSignature` indicating it's a placeholder for an unmodeled reference
type (since there is a 1:1 correspondence between WasmSignature objects
and types in the type section).
Then the object file parsers for the type and element sections are expanded
to parse encoded reference types and discard any unmodeled fields.

GitOrigin-RevId: 7f409cd82b322038f08a984a07377758e76b0e4c
diff --git a/wasm/InputChunks.h b/wasm/InputChunks.h
index 1e43083..ad1d45e 100644
--- a/wasm/InputChunks.h
+++ b/wasm/InputChunks.h
@@ -259,10 +259,13 @@
         file->codeSection->Content.slice(inputSectionOffset, function->Size);
     debugName = function->DebugName;
     comdat = function->Comdat;
+    assert(s.Kind != WasmSignature::Placeholder);
   }
 
   InputFunction(StringRef name, const WasmSignature &s)
-      : InputChunk(nullptr, InputChunk::Function, name), signature(s) {}
+      : InputChunk(nullptr, InputChunk::Function, name), signature(s) {
+    assert(s.Kind == WasmSignature::Function);
+  }
 
   static bool classof(const InputChunk *c) {
     return c->kind() == InputChunk::Function ||
diff --git a/wasm/InputElement.h b/wasm/InputElement.h
index 46e21d7..10dc2a3 100644
--- a/wasm/InputElement.h
+++ b/wasm/InputElement.h
@@ -76,7 +76,9 @@
 class InputTag : public InputElement {
 public:
   InputTag(const WasmSignature &s, const WasmTag &t, ObjFile *f)
-      : InputElement(t.SymbolName, f), signature(s) {}
+      : InputElement(t.SymbolName, f), signature(s) {
+    assert(s.Kind == WasmSignature::Tag);
+  }
 
   const WasmSignature &signature;
 };
diff --git a/wasm/InputFiles.cpp b/wasm/InputFiles.cpp
index f5e946a..f43c39b 100644
--- a/wasm/InputFiles.cpp
+++ b/wasm/InputFiles.cpp
@@ -81,6 +81,9 @@
     std::unique_ptr<Binary> bin =
         CHECK(createBinary(mb), mb.getBufferIdentifier());
     auto *obj = cast<WasmObjectFile>(bin.get());
+    if (obj->hasUnmodeledTypes())
+      fatal(toString(mb.getBufferIdentifier()) +
+            "file has unmodeled reference or GC types");
     if (obj->isSharedObject())
       return make<SharedFile>(mb);
     return make<ObjFile>(mb, archiveName, lazy);
diff --git a/wasm/WriterUtils.cpp b/wasm/WriterUtils.cpp
index 418192f..cdd2c42 100644
--- a/wasm/WriterUtils.cpp
+++ b/wasm/WriterUtils.cpp
@@ -35,6 +35,8 @@
     return "funcref";
   case ValType::EXTERNREF:
     return "externref";
+  case ValType::OTHERREF:
+    return "otherref";
   }
   llvm_unreachable("Invalid wasm::ValType");
 }