1 //===-- WebAssemblyTypeUtilities.cpp - WebAssembly Type Utility Functions -===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 ///
9 /// \file
10 /// This file implements several utility functions for WebAssembly type parsing.
11 ///
12 //===----------------------------------------------------------------------===//
13 
14 #include "WebAssemblyTypeUtilities.h"
15 #include "llvm/ADT/StringSwitch.h"
16 
17 // Get register classes enum.
18 #define GET_REGINFO_ENUM
19 #include "WebAssemblyGenRegisterInfo.inc"
20 
21 using namespace llvm;
22 
parseType(StringRef Type)23 Optional<wasm::ValType> WebAssembly::parseType(StringRef Type) {
24   // FIXME: can't use StringSwitch because wasm::ValType doesn't have a
25   // "invalid" value.
26   if (Type == "i32")
27     return wasm::ValType::I32;
28   if (Type == "i64")
29     return wasm::ValType::I64;
30   if (Type == "f32")
31     return wasm::ValType::F32;
32   if (Type == "f64")
33     return wasm::ValType::F64;
34   if (Type == "v128" || Type == "i8x16" || Type == "i16x8" || Type == "i32x4" ||
35       Type == "i64x2" || Type == "f32x4" || Type == "f64x2")
36     return wasm::ValType::V128;
37   if (Type == "funcref")
38     return wasm::ValType::FUNCREF;
39   if (Type == "externref")
40     return wasm::ValType::EXTERNREF;
41   return Optional<wasm::ValType>();
42 }
43 
parseHeapType(StringRef Type)44 WebAssembly::HeapType WebAssembly::parseHeapType(StringRef Type) {
45   return StringSwitch<WebAssembly::HeapType>(Type)
46       .Case("extern", WebAssembly::HeapType::Externref)
47       .Case("func", WebAssembly::HeapType::Funcref)
48       .Default(WebAssembly::HeapType::Invalid);
49 }
50 
parseBlockType(StringRef Type)51 WebAssembly::BlockType WebAssembly::parseBlockType(StringRef Type) {
52   // Multivalue block types are handled separately in parseSignature
53   return StringSwitch<WebAssembly::BlockType>(Type)
54       .Case("i32", WebAssembly::BlockType::I32)
55       .Case("i64", WebAssembly::BlockType::I64)
56       .Case("f32", WebAssembly::BlockType::F32)
57       .Case("f64", WebAssembly::BlockType::F64)
58       .Case("v128", WebAssembly::BlockType::V128)
59       .Case("funcref", WebAssembly::BlockType::Funcref)
60       .Case("externref", WebAssembly::BlockType::Externref)
61       .Case("void", WebAssembly::BlockType::Void)
62       .Default(WebAssembly::BlockType::Invalid);
63 }
64 
parseMVT(StringRef Type)65 MVT WebAssembly::parseMVT(StringRef Type) {
66   return StringSwitch<MVT>(Type)
67       .Case("i32", MVT::i32)
68       .Case("i64", MVT::i64)
69       .Case("f32", MVT::f32)
70       .Case("f64", MVT::f64)
71       .Case("i64", MVT::i64)
72       .Case("v16i8", MVT::v16i8)
73       .Case("v8i16", MVT::v8i16)
74       .Case("v4i32", MVT::v4i32)
75       .Case("v2i64", MVT::v2i64)
76       .Case("funcref", MVT::funcref)
77       .Case("externref", MVT::externref)
78       .Default(MVT::INVALID_SIMPLE_VALUE_TYPE);
79 }
80 
81 // We have various enums representing a subset of these types, use this
82 // function to convert any of them to text.
anyTypeToString(unsigned Type)83 const char *WebAssembly::anyTypeToString(unsigned Type) {
84   switch (Type) {
85   case wasm::WASM_TYPE_I32:
86     return "i32";
87   case wasm::WASM_TYPE_I64:
88     return "i64";
89   case wasm::WASM_TYPE_F32:
90     return "f32";
91   case wasm::WASM_TYPE_F64:
92     return "f64";
93   case wasm::WASM_TYPE_V128:
94     return "v128";
95   case wasm::WASM_TYPE_FUNCREF:
96     return "funcref";
97   case wasm::WASM_TYPE_EXTERNREF:
98     return "externref";
99   case wasm::WASM_TYPE_FUNC:
100     return "func";
101   case wasm::WASM_TYPE_NORESULT:
102     return "void";
103   default:
104     return "invalid_type";
105   }
106 }
107 
typeToString(wasm::ValType Type)108 const char *WebAssembly::typeToString(wasm::ValType Type) {
109   return anyTypeToString(static_cast<unsigned>(Type));
110 }
111 
typeListToString(ArrayRef<wasm::ValType> List)112 std::string WebAssembly::typeListToString(ArrayRef<wasm::ValType> List) {
113   std::string S;
114   for (const auto &Type : List) {
115     if (&Type != &List[0])
116       S += ", ";
117     S += WebAssembly::typeToString(Type);
118   }
119   return S;
120 }
121 
signatureToString(const wasm::WasmSignature * Sig)122 std::string WebAssembly::signatureToString(const wasm::WasmSignature *Sig) {
123   std::string S("(");
124   S += typeListToString(Sig->Params);
125   S += ") -> (";
126   S += typeListToString(Sig->Returns);
127   S += ")";
128   return S;
129 }
130 
toValType(MVT Type)131 wasm::ValType WebAssembly::toValType(MVT Type) {
132   switch (Type.SimpleTy) {
133   case MVT::i32:
134     return wasm::ValType::I32;
135   case MVT::i64:
136     return wasm::ValType::I64;
137   case MVT::f32:
138     return wasm::ValType::F32;
139   case MVT::f64:
140     return wasm::ValType::F64;
141   case MVT::v16i8:
142   case MVT::v8i16:
143   case MVT::v4i32:
144   case MVT::v2i64:
145   case MVT::v4f32:
146   case MVT::v2f64:
147     return wasm::ValType::V128;
148   case MVT::funcref:
149     return wasm::ValType::FUNCREF;
150   case MVT::externref:
151     return wasm::ValType::EXTERNREF;
152   default:
153     llvm_unreachable("unexpected type");
154   }
155 }
156 
regClassToValType(unsigned RC)157 wasm::ValType WebAssembly::regClassToValType(unsigned RC) {
158   switch (RC) {
159   case WebAssembly::I32RegClassID:
160     return wasm::ValType::I32;
161   case WebAssembly::I64RegClassID:
162     return wasm::ValType::I64;
163   case WebAssembly::F32RegClassID:
164     return wasm::ValType::F32;
165   case WebAssembly::F64RegClassID:
166     return wasm::ValType::F64;
167   case WebAssembly::V128RegClassID:
168     return wasm::ValType::V128;
169   case WebAssembly::FUNCREFRegClassID:
170     return wasm::ValType::FUNCREF;
171   case WebAssembly::EXTERNREFRegClassID:
172     return wasm::ValType::EXTERNREF;
173   default:
174     llvm_unreachable("unexpected type");
175   }
176 }
177