Add Type comparison methods (#2580)

Code is based on the work of SoniEx2.

Co-authored-by: Zoltan Herczeg <hzmester@freemail.hu>
diff --git a/include/wabt/type.h b/include/wabt/type.h
index d0e85d9..3023416 100644
--- a/include/wabt/type.h
+++ b/include/wabt/type.h
@@ -60,19 +60,40 @@
 
   Type() = default;  // Provided so Type can be member of a union.
   Type(int32_t code)
-      : enum_(static_cast<Enum>(code)), type_index_(kInvalidIndex) {}
-  Type(Enum e) : enum_(e), type_index_(kInvalidIndex) {}
+      : enum_(static_cast<Enum>(code)), type_index_(0) {
+    assert(!EnumIsReferenceWithIndex(enum_));
+  }
+  Type(Enum e) : enum_(e), type_index_(0) {
+    assert(!EnumIsReferenceWithIndex(enum_));
+  }
   Type(Enum e, Index type_index) : enum_(e), type_index_(type_index) {
-    assert(e == Enum::Reference);
+    assert(EnumIsReferenceWithIndex(e));
   }
   constexpr operator Enum() const { return enum_; }
 
+  friend constexpr bool operator==(const Type a, const Type b) {
+    return a.enum_ == b.enum_ && a.type_index_ == b.type_index_;
+  }
+  friend constexpr bool operator!=(const Type a, const Type b) {
+    return !(a == b);
+  }
+  friend constexpr bool operator==(const Type ty, const Enum code) {
+    return ty.enum_ == code;
+  }
+  friend constexpr bool operator!=(const Type ty, const Enum code) {
+    return !(ty == code);
+  }
+  friend constexpr bool operator<(const Type a, const Type b) {
+    return a.enum_ == b.enum_ ? a.type_index_ < b.type_index_
+                              : a.enum_ < b.enum_;
+  }
+
   bool IsRef() const {
     return enum_ == Type::ExternRef || enum_ == Type::FuncRef ||
            enum_ == Type::Reference || enum_ == Type::ExnRef;
   }
 
-  bool IsReferenceWithIndex() const { return enum_ == Type::Reference; }
+  bool IsReferenceWithIndex() const { return EnumIsReferenceWithIndex(enum_); }
 
   bool IsNullableRef() const {
     // Currently all reftypes are nullable
@@ -159,8 +180,15 @@
   }
 
  private:
+  static bool EnumIsReferenceWithIndex(Enum value) {
+    return value == Type::Reference;
+  }
+
   Enum enum_;
-  Index type_index_;  // Only used for for Type::Reference
+  // This index is 0 for non-references, so a zeroed
+  // memory area represents a valid Type::Any type.
+  // It contains an index for references with type index.
+  Index type_index_;
 };
 
 }  // namespace wabt
diff --git a/src/binary-reader.cc b/src/binary-reader.cc
index e1859a1..6828435 100644
--- a/src/binary-reader.cc
+++ b/src/binary-reader.cc
@@ -376,9 +376,7 @@
 }
 
 Result BinaryReader::ReadRefType(Type* out_value, const char* desc) {
-  uint32_t type = 0;
-  CHECK_RESULT(ReadS32Leb128(&type, desc));
-  *out_value = static_cast<Type>(type);
+  CHECK_RESULT(ReadType(out_value, desc));
   ERROR_UNLESS(out_value->IsRef(), "%s must be a reference type", desc);
   return Result::Ok;
 }
diff --git a/src/type-checker.cc b/src/type-checker.cc
index 96e4153..90dda71 100644
--- a/src/type-checker.cc
+++ b/src/type-checker.cc
@@ -233,11 +233,6 @@
     return Result::Ok;
   }
 
-  if (expected == Type::Reference && actual == Type::Reference) {
-    return expected.GetReferenceIndex() == actual.GetReferenceIndex()
-               ? Result::Ok
-               : Result::Error;
-  }
   if (actual != expected) {
     return Result::Error;
   }
@@ -524,7 +519,7 @@
   Type type;
   Result result = PeekType(0, &type);
   if (!type.IsReferenceWithIndex()) {
-    type = Type::Reference;
+    type = Type(Type::Reference, kInvalidIndex);
   }
   result |= PopAndCheck1Type(type, "call_ref");
   if (Succeeded(result)) {
@@ -814,7 +809,7 @@
   Type type;
   Result result = PeekType(0, &type);
   if (!type.IsRef()) {
-    type = Type::Reference;
+    type = Type(Type::Reference, kInvalidIndex);
   }
   result |= PopAndCheck1Type(type, "ref.is_null");
   PushType(Type::I32);
diff --git a/test/dump/typed-func-ref-signature.txt b/test/dump/typed-func-ref-signature.txt
new file mode 100644
index 0000000..506affe
--- /dev/null
+++ b/test/dump/typed-func-ref-signature.txt
@@ -0,0 +1,118 @@
+;;; TOOL: run-objdump
+;;; ARGS0: -v --enable-function-references
+(module
+  (type $t1 (func))
+  (type $t2 (func))
+  (type $t3 (func))
+
+  (func $f1 (param (ref $t1)) )
+  (func $f2 (param (ref $t2)) )
+  (func $f3 (param (ref $t3)) )
+  (func $f4 (param (ref $t3)) )
+  (func $f5 (param (ref $t2)) )
+  (func $f6 (param (ref $t1)) )
+)
+(;; STDERR ;;;
+0000000: 0061 736d                                 ; WASM_BINARY_MAGIC
+0000004: 0100 0000                                 ; WASM_BINARY_VERSION
+; section "Type" (1)
+0000008: 01                                        ; section code
+0000009: 00                                        ; section size (guess)
+000000a: 06                                        ; num types
+; func type 0
+000000b: 60                                        ; func
+000000c: 00                                        ; num params
+000000d: 00                                        ; num results
+; func type 1
+000000e: 60                                        ; func
+000000f: 00                                        ; num params
+0000010: 00                                        ; num results
+; func type 2
+0000011: 60                                        ; func
+0000012: 00                                        ; num params
+0000013: 00                                        ; num results
+; func type 3
+0000014: 60                                        ; func
+0000015: 01                                        ; num params
+0000016: 6b                                        ; (ref 0)
+0000017: 00                                        ; (ref 0)
+0000018: 00                                        ; num results
+; func type 4
+0000019: 60                                        ; func
+000001a: 01                                        ; num params
+000001b: 6b                                        ; (ref 1)
+000001c: 01                                        ; (ref 1)
+000001d: 00                                        ; num results
+; func type 5
+000001e: 60                                        ; func
+000001f: 01                                        ; num params
+0000020: 6b                                        ; (ref 2)
+0000021: 02                                        ; (ref 2)
+0000022: 00                                        ; num results
+0000009: 19                                        ; FIXUP section size
+; section "Function" (3)
+0000023: 03                                        ; section code
+0000024: 00                                        ; section size (guess)
+0000025: 06                                        ; num functions
+0000026: 03                                        ; function 0 signature index
+0000027: 04                                        ; function 1 signature index
+0000028: 05                                        ; function 2 signature index
+0000029: 05                                        ; function 3 signature index
+000002a: 04                                        ; function 4 signature index
+000002b: 03                                        ; function 5 signature index
+0000024: 07                                        ; FIXUP section size
+; section "Code" (10)
+000002c: 0a                                        ; section code
+000002d: 00                                        ; section size (guess)
+000002e: 06                                        ; num functions
+; function body 0
+000002f: 00                                        ; func body size (guess)
+0000030: 00                                        ; local decl count
+0000031: 0b                                        ; end
+000002f: 02                                        ; FIXUP func body size
+; function body 1
+0000032: 00                                        ; func body size (guess)
+0000033: 00                                        ; local decl count
+0000034: 0b                                        ; end
+0000032: 02                                        ; FIXUP func body size
+; function body 2
+0000035: 00                                        ; func body size (guess)
+0000036: 00                                        ; local decl count
+0000037: 0b                                        ; end
+0000035: 02                                        ; FIXUP func body size
+; function body 3
+0000038: 00                                        ; func body size (guess)
+0000039: 00                                        ; local decl count
+000003a: 0b                                        ; end
+0000038: 02                                        ; FIXUP func body size
+; function body 4
+000003b: 00                                        ; func body size (guess)
+000003c: 00                                        ; local decl count
+000003d: 0b                                        ; end
+000003b: 02                                        ; FIXUP func body size
+; function body 5
+000003e: 00                                        ; func body size (guess)
+000003f: 00                                        ; local decl count
+0000040: 0b                                        ; end
+000003e: 02                                        ; FIXUP func body size
+000002d: 13                                        ; FIXUP section size
+;;; STDERR ;;)
+(;; STDOUT ;;;
+
+typed-func-ref-signature.wasm:	file format wasm 0x1
+
+Code Disassembly:
+
+000030 func[0]:
+ 000031: 0b                         | end
+000033 func[1]:
+ 000034: 0b                         | end
+000036 func[2]:
+ 000037: 0b                         | end
+000039 func[3]:
+ 00003a: 0b                         | end
+00003c func[4]:
+ 00003d: 0b                         | end
+00003f func[5]:
+ 000040: 0b                         | end
+;;; STDOUT ;;)