1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2  * vim: set ts=8 sts=2 et sw=2 tw=80:
3  *
4  * Copyright 2021 Mozilla Foundation
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 
19 #include "wasm/WasmValType.h"
20 
21 #include "js/friend/ErrorMessages.h"  // JSMSG_*
22 #include "js/Printf.h"
23 #include "js/Value.h"
24 #include "vm/StringType.h"
25 #include "wasm/WasmJS.h"
26 
27 using namespace js;
28 using namespace js::wasm;
29 
ToValType(JSContext * cx,HandleValue v,ValType * out)30 bool wasm::ToValType(JSContext* cx, HandleValue v, ValType* out) {
31   RootedString typeStr(cx, ToString(cx, v));
32   if (!typeStr) {
33     return false;
34   }
35 
36   RootedLinearString typeLinearStr(cx, typeStr->ensureLinear(cx));
37   if (!typeLinearStr) {
38     return false;
39   }
40 
41   if (StringEqualsLiteral(typeLinearStr, "i32")) {
42     *out = ValType::I32;
43   } else if (StringEqualsLiteral(typeLinearStr, "i64")) {
44     *out = ValType::I64;
45   } else if (StringEqualsLiteral(typeLinearStr, "f32")) {
46     *out = ValType::F32;
47   } else if (StringEqualsLiteral(typeLinearStr, "f64")) {
48     *out = ValType::F64;
49 #ifdef ENABLE_WASM_SIMD
50   } else if (SimdAvailable(cx) && StringEqualsLiteral(typeLinearStr, "v128")) {
51     *out = ValType::V128;
52 #endif
53   } else if (StringEqualsLiteral(typeLinearStr, "funcref")) {
54     *out = RefType::func();
55   } else if (StringEqualsLiteral(typeLinearStr, "externref")) {
56     *out = RefType::extern_();
57 #ifdef ENABLE_WASM_GC
58   } else if (GcAvailable(cx) && StringEqualsLiteral(typeLinearStr, "eqref")) {
59     *out = RefType::eq();
60 #endif
61   } else {
62     JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr,
63                              JSMSG_WASM_BAD_STRING_VAL_TYPE);
64     return false;
65   }
66 
67   return true;
68 }
69 
ToString(ValType type)70 UniqueChars wasm::ToString(ValType type) {
71   const char* literal = nullptr;
72   switch (type.kind()) {
73     case ValType::I32:
74       literal = "i32";
75       break;
76     case ValType::I64:
77       literal = "i64";
78       break;
79     case ValType::V128:
80       literal = "v128";
81       break;
82     case ValType::F32:
83       literal = "f32";
84       break;
85     case ValType::F64:
86       literal = "f64";
87       break;
88     case ValType::Ref:
89       if (type.isNullable() && !type.isTypeIndex()) {
90         switch (type.refTypeKind()) {
91           case RefType::Func:
92             literal = "funcref";
93             break;
94           case RefType::Extern:
95             literal = "externref";
96             break;
97           case RefType::Eq:
98             literal = "eqref";
99             break;
100           case RefType::TypeIndex:
101             MOZ_ASSERT_UNREACHABLE();
102         }
103       } else {
104         const char* heapType = nullptr;
105         switch (type.refTypeKind()) {
106           case RefType::Func:
107             heapType = "func";
108             break;
109           case RefType::Extern:
110             heapType = "extern";
111             break;
112           case RefType::Eq:
113             heapType = "eq";
114             break;
115           case RefType::TypeIndex:
116             return JS_smprintf("(ref %s%d)", type.isNullable() ? "null " : "",
117                                type.refType().typeIndex());
118         }
119         return JS_smprintf("(ref %s%s)", type.isNullable() ? "null " : "",
120                            heapType);
121       }
122       break;
123     case ValType::Rtt:
124       return JS_smprintf("(rtt %d %d)", type.rttDepth(), type.typeIndex());
125   }
126   return JS_smprintf("%s", literal);
127 }
128 
ToString(const Maybe<ValType> & type)129 UniqueChars wasm::ToString(const Maybe<ValType>& type) {
130   return type ? ToString(type.ref()) : JS_smprintf("%s", "void");
131 }
132