testWasmRefSubtypes.cpp (8995B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 #include "jsapi-tests/tests.h" 6 7 #include "wasm/WasmValType.h" 8 9 BEGIN_TEST(testWasmRefType_LUB) { 10 using namespace js; 11 using namespace wasm; 12 13 struct TestCase { 14 RefType a; 15 RefType b; 16 RefType lub; 17 }; 18 19 // For the any hierarchy: 20 // 21 // s1 a1 22 // │ └┐ 23 // s2 s3 24 25 MutableTypeContext types = new TypeContext(); 26 MutableRecGroup recGroup = types->startRecGroup(4); 27 28 TypeDef* tA1 = &recGroup->type(0); 29 *tA1 = ArrayType(StorageType::I16, true); 30 31 TypeDef* tS1 = &recGroup->type(1); 32 *tS1 = StructType(); 33 34 TypeDef* tS2 = &recGroup->type(2); 35 FieldTypeVector s2Fields; 36 CHECK(s2Fields.append(FieldType(StorageType::I32, false))); 37 *tS2 = StructType(std::move(s2Fields)); 38 tS2->setSuperTypeDef(tS1); 39 40 TypeDef* tS3 = &recGroup->type(3); 41 FieldTypeVector s3Fields; 42 CHECK(s3Fields.append(FieldType(StorageType::I64, false))); 43 *tS3 = StructType(std::move(s3Fields)); 44 tS3->setSuperTypeDef(tS1); 45 46 CHECK(types->endRecGroup()); 47 48 RefType a1 = RefType::fromTypeDef(tA1, true); 49 RefType s1 = RefType::fromTypeDef(tS1, true); 50 RefType s2 = RefType::fromTypeDef(tS2, true); 51 RefType s3 = RefType::fromTypeDef(tS3, true); 52 53 TestCase testCases[] = { 54 // 55 // Tops and bottoms 56 // 57 58 // any, any -> any 59 {RefType::any(), RefType::any(), RefType::any()}, 60 {RefType::any().asNonNullable(), RefType::any(), RefType::any()}, 61 {RefType::any().asNonNullable(), RefType::any().asNonNullable(), 62 RefType::any().asNonNullable()}, 63 64 // none, none -> none 65 {RefType::none(), RefType::none(), RefType::none()}, 66 {RefType::none().asNonNullable(), RefType::none(), RefType::none()}, 67 {RefType::none().asNonNullable(), RefType::none().asNonNullable(), 68 RefType::none().asNonNullable()}, 69 70 // none, any -> any 71 {RefType::none(), RefType::any(), RefType::any()}, 72 {RefType::none().asNonNullable(), RefType::any(), RefType::any()}, 73 {RefType::none(), RefType::any().asNonNullable(), RefType::any()}, 74 {RefType::none().asNonNullable(), RefType::any().asNonNullable(), 75 RefType::any().asNonNullable()}, 76 77 // func, func -> func 78 {RefType::func(), RefType::func(), RefType::func()}, 79 {RefType::func().asNonNullable(), RefType::func(), RefType::func()}, 80 {RefType::func().asNonNullable(), RefType::func().asNonNullable(), 81 RefType::func().asNonNullable()}, 82 83 // nofunc, nofunc -> nofunc 84 {RefType::nofunc(), RefType::nofunc(), RefType::nofunc()}, 85 {RefType::nofunc().asNonNullable(), RefType::nofunc(), RefType::nofunc()}, 86 {RefType::nofunc().asNonNullable(), RefType::nofunc().asNonNullable(), 87 RefType::nofunc().asNonNullable()}, 88 89 // nofunc, func -> func 90 {RefType::nofunc(), RefType::func(), RefType::func()}, 91 {RefType::nofunc().asNonNullable(), RefType::func(), RefType::func()}, 92 {RefType::nofunc(), RefType::func().asNonNullable(), RefType::func()}, 93 {RefType::nofunc().asNonNullable(), RefType::func().asNonNullable(), 94 RefType::func().asNonNullable()}, 95 96 // extern, extern -> extern 97 {RefType::extern_(), RefType::extern_(), RefType::extern_()}, 98 {RefType::extern_().asNonNullable(), RefType::extern_(), 99 RefType::extern_()}, 100 {RefType::extern_().asNonNullable(), RefType::extern_().asNonNullable(), 101 RefType::extern_().asNonNullable()}, 102 103 // noextern, noextern -> noextern 104 {RefType::noextern(), RefType::noextern(), RefType::noextern()}, 105 {RefType::noextern().asNonNullable(), RefType::noextern(), 106 RefType::noextern()}, 107 {RefType::noextern().asNonNullable(), RefType::noextern().asNonNullable(), 108 RefType::noextern().asNonNullable()}, 109 110 // noextern, extern -> extern 111 {RefType::noextern(), RefType::extern_(), RefType::extern_()}, 112 {RefType::noextern().asNonNullable(), RefType::extern_(), 113 RefType::extern_()}, 114 {RefType::noextern(), RefType::extern_().asNonNullable(), 115 RefType::extern_()}, 116 {RefType::noextern().asNonNullable(), RefType::extern_().asNonNullable(), 117 RefType::extern_().asNonNullable()}, 118 119 // exn, exn -> exn 120 {RefType::exn(), RefType::exn(), RefType::exn()}, 121 {RefType::exn().asNonNullable(), RefType::exn(), RefType::exn()}, 122 {RefType::exn().asNonNullable(), RefType::exn().asNonNullable(), 123 RefType::exn().asNonNullable()}, 124 125 // noexn, noexn -> noexn 126 {RefType::noexn(), RefType::noexn(), RefType::noexn()}, 127 {RefType::noexn().asNonNullable(), RefType::noexn(), RefType::noexn()}, 128 {RefType::noexn().asNonNullable(), RefType::noexn().asNonNullable(), 129 RefType::noexn().asNonNullable()}, 130 131 // noexn, exn -> exn 132 {RefType::noexn(), RefType::exn(), RefType::exn()}, 133 {RefType::noexn().asNonNullable(), RefType::exn(), RefType::exn()}, 134 {RefType::noexn(), RefType::exn().asNonNullable(), RefType::exn()}, 135 {RefType::noexn().asNonNullable(), RefType::exn().asNonNullable(), 136 RefType::exn().asNonNullable()}, 137 138 // 139 // concrete type, abstract types 140 // 141 142 // $a1, $a1 -> array 143 {a1, a1, a1}, 144 {a1.asNonNullable(), a1, a1}, 145 {a1.asNonNullable(), a1.asNonNullable(), a1.asNonNullable()}, 146 147 // $a1, any -> any 148 {a1, RefType::any(), RefType::any()}, 149 {a1, RefType::any().asNonNullable(), RefType::any()}, 150 {a1.asNonNullable(), RefType::any(), RefType::any()}, 151 {a1.asNonNullable(), RefType::any().asNonNullable(), 152 RefType::any().asNonNullable()}, 153 154 // $a1, eq -> eq 155 {a1, RefType::eq(), RefType::eq()}, 156 {a1.asNonNullable(), RefType::eq(), RefType::eq()}, 157 {a1, RefType::eq().asNonNullable(), RefType::eq()}, 158 {a1.asNonNullable(), RefType::eq().asNonNullable(), 159 RefType::eq().asNonNullable()}, 160 161 // $a1, i31 -> eq 162 {a1, RefType::i31(), RefType::eq()}, 163 {a1.asNonNullable(), RefType::i31(), RefType::eq()}, 164 {a1, RefType::i31().asNonNullable(), RefType::eq()}, 165 {a1.asNonNullable(), RefType::i31().asNonNullable(), 166 RefType::eq().asNonNullable()}, 167 168 // $a1, struct -> eq 169 {a1, RefType::struct_(), RefType::eq()}, 170 {a1.asNonNullable(), RefType::struct_(), RefType::eq()}, 171 {a1, RefType::struct_().asNonNullable(), RefType::eq()}, 172 {a1.asNonNullable(), RefType::struct_().asNonNullable(), 173 RefType::eq().asNonNullable()}, 174 175 // $a1, array -> array 176 {a1, RefType::array(), RefType::array()}, 177 {a1.asNonNullable(), RefType::array(), RefType::array()}, 178 {a1, RefType::array().asNonNullable(), RefType::array()}, 179 {a1.asNonNullable(), RefType::array().asNonNullable(), 180 RefType::array().asNonNullable()}, 181 182 // $a1, none -> $a1 183 {a1, RefType::none(), a1}, 184 {a1, RefType::none().asNonNullable(), a1}, 185 {a1.asNonNullable(), RefType::none(), a1}, 186 {a1.asNonNullable(), RefType::none().asNonNullable(), a1.asNonNullable()}, 187 188 // 189 // concrete subtypes 190 // 191 192 // $s1, $s2 -> $s1 193 {s1, s2, s1}, 194 {s1.asNonNullable(), s2, s1}, 195 {s1, s2.asNonNullable(), s1}, 196 {s1.asNonNullable(), s2.asNonNullable(), s1.asNonNullable()}, 197 198 // 199 // concrete sibling types 200 // 201 202 // $s2, $s3 -> $s1 203 {s2, s3, s1}, 204 {s2.asNonNullable(), s3, s1}, 205 {s2, s3.asNonNullable(), s1}, 206 {s2.asNonNullable(), s3.asNonNullable(), s1.asNonNullable()}, 207 208 // 209 // unrelated concrete types 210 // 211 212 // $s1, $a1 -> eq 213 {s1, a1, RefType::eq()}, 214 {s1.asNonNullable(), a1, RefType::eq()}, 215 {s1, a1.asNonNullable(), RefType::eq()}, 216 {s1.asNonNullable(), a1.asNonNullable(), RefType::eq().asNonNullable()}, 217 }; 218 219 #define CHECK_LUB(a, b, expected) \ 220 do { \ 221 RefType _actual = RefType::leastUpperBound((a), (b)); \ 222 if (_actual != (expected)) { \ 223 return fail(JSAPITestString("bad LUB of ") + \ 224 wasm::ToString((a), types).get() + " and " + \ 225 wasm::ToString((b), types).get() + ": expected " + \ 226 wasm::ToString((expected), types).get() + ", got " + \ 227 wasm::ToString(_actual, types).get(), \ 228 __FILE__, __LINE__); \ 229 } \ 230 } while (false) 231 232 for (const TestCase& testCase : testCases) { 233 // LUB is commutative. 234 CHECK_LUB(testCase.a, testCase.b, testCase.lub); 235 CHECK_LUB(testCase.b, testCase.a, testCase.lub); 236 } 237 238 return true; 239 } 240 END_TEST(testWasmRefType_LUB)