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 ;;)