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 #include "llvm/CodeGen/TargetRegisterInfo.h" 17 18 // Get register classes enum. 19 #define GET_REGINFO_ENUM 20 #include "WebAssemblyGenRegisterInfo.inc" 21 22 using namespace llvm; 23 24 std::optional<wasm::ValType> WebAssembly::parseType(StringRef Type) { 25 // FIXME: can't use StringSwitch because wasm::ValType doesn't have a 26 // "invalid" value. 27 if (Type == "i32") 28 return wasm::ValType::I32; 29 if (Type == "i64") 30 return wasm::ValType::I64; 31 if (Type == "f32") 32 return wasm::ValType::F32; 33 if (Type == "f64") 34 return wasm::ValType::F64; 35 if (Type == "v128" || Type == "i8x16" || Type == "i16x8" || Type == "i32x4" || 36 Type == "i64x2" || Type == "f32x4" || Type == "f64x2") 37 return wasm::ValType::V128; 38 if (Type == "funcref") 39 return wasm::ValType::FUNCREF; 40 if (Type == "externref") 41 return wasm::ValType::EXTERNREF; 42 return std::nullopt; 43 } 44 45 WebAssembly::BlockType WebAssembly::parseBlockType(StringRef Type) { 46 // Multivalue block types are handled separately in parseSignature 47 return StringSwitch<WebAssembly::BlockType>(Type) 48 .Case("i32", WebAssembly::BlockType::I32) 49 .Case("i64", WebAssembly::BlockType::I64) 50 .Case("f32", WebAssembly::BlockType::F32) 51 .Case("f64", WebAssembly::BlockType::F64) 52 .Case("v128", WebAssembly::BlockType::V128) 53 .Case("funcref", WebAssembly::BlockType::Funcref) 54 .Case("externref", WebAssembly::BlockType::Externref) 55 .Case("void", WebAssembly::BlockType::Void) 56 .Default(WebAssembly::BlockType::Invalid); 57 } 58 59 MVT WebAssembly::parseMVT(StringRef Type) { 60 return StringSwitch<MVT>(Type) 61 .Case("i32", MVT::i32) 62 .Case("i64", MVT::i64) 63 .Case("f32", MVT::f32) 64 .Case("f64", MVT::f64) 65 .Case("i64", MVT::i64) 66 .Case("v16i8", MVT::v16i8) 67 .Case("v8i16", MVT::v8i16) 68 .Case("v4i32", MVT::v4i32) 69 .Case("v2i64", MVT::v2i64) 70 .Case("funcref", MVT::funcref) 71 .Case("externref", MVT::externref) 72 .Default(MVT::INVALID_SIMPLE_VALUE_TYPE); 73 } 74 75 // We have various enums representing a subset of these types, use this 76 // function to convert any of them to text. 77 const char *WebAssembly::anyTypeToString(unsigned Type) { 78 switch (Type) { 79 case wasm::WASM_TYPE_I32: 80 return "i32"; 81 case wasm::WASM_TYPE_I64: 82 return "i64"; 83 case wasm::WASM_TYPE_F32: 84 return "f32"; 85 case wasm::WASM_TYPE_F64: 86 return "f64"; 87 case wasm::WASM_TYPE_V128: 88 return "v128"; 89 case wasm::WASM_TYPE_FUNCREF: 90 return "funcref"; 91 case wasm::WASM_TYPE_EXTERNREF: 92 return "externref"; 93 case wasm::WASM_TYPE_FUNC: 94 return "func"; 95 case wasm::WASM_TYPE_NORESULT: 96 return "void"; 97 default: 98 return "invalid_type"; 99 } 100 } 101 102 const char *WebAssembly::typeToString(wasm::ValType Type) { 103 return anyTypeToString(static_cast<unsigned>(Type)); 104 } 105 106 std::string WebAssembly::typeListToString(ArrayRef<wasm::ValType> List) { 107 std::string S; 108 for (const auto &Type : List) { 109 if (&Type != &List[0]) 110 S += ", "; 111 S += WebAssembly::typeToString(Type); 112 } 113 return S; 114 } 115 116 std::string WebAssembly::signatureToString(const wasm::WasmSignature *Sig) { 117 std::string S("("); 118 S += typeListToString(Sig->Params); 119 S += ") -> ("; 120 S += typeListToString(Sig->Returns); 121 S += ")"; 122 return S; 123 } 124 125 wasm::ValType WebAssembly::toValType(MVT Type) { 126 switch (Type.SimpleTy) { 127 case MVT::i32: 128 return wasm::ValType::I32; 129 case MVT::i64: 130 return wasm::ValType::I64; 131 case MVT::f32: 132 return wasm::ValType::F32; 133 case MVT::f64: 134 return wasm::ValType::F64; 135 case MVT::v16i8: 136 case MVT::v8i16: 137 case MVT::v4i32: 138 case MVT::v2i64: 139 case MVT::v4f32: 140 case MVT::v2f64: 141 return wasm::ValType::V128; 142 case MVT::funcref: 143 return wasm::ValType::FUNCREF; 144 case MVT::externref: 145 return wasm::ValType::EXTERNREF; 146 default: 147 llvm_unreachable("unexpected type"); 148 } 149 } 150 151 wasm::ValType WebAssembly::regClassToValType(unsigned RC) { 152 switch (RC) { 153 case WebAssembly::I32RegClassID: 154 return wasm::ValType::I32; 155 case WebAssembly::I64RegClassID: 156 return wasm::ValType::I64; 157 case WebAssembly::F32RegClassID: 158 return wasm::ValType::F32; 159 case WebAssembly::F64RegClassID: 160 return wasm::ValType::F64; 161 case WebAssembly::V128RegClassID: 162 return wasm::ValType::V128; 163 case WebAssembly::FUNCREFRegClassID: 164 return wasm::ValType::FUNCREF; 165 case WebAssembly::EXTERNREFRegClassID: 166 return wasm::ValType::EXTERNREF; 167 default: 168 llvm_unreachable("unexpected type"); 169 } 170 } 171 172 wasm::ValType WebAssembly::regClassToValType(const TargetRegisterClass *RC) { 173 assert(RC != nullptr); 174 return regClassToValType(RC->getID()); 175 } 176 177 void WebAssembly::wasmSymbolSetType(MCSymbolWasm *Sym, const Type *GlobalVT, 178 const SmallVector<MVT, 1> &VTs) { 179 assert(!Sym->getType()); 180 181 // Tables are represented as Arrays in LLVM IR therefore 182 // they reach this point as aggregate Array types with an element type 183 // that is a reference type. 184 wasm::ValType ValTy; 185 bool IsTable = false; 186 if (GlobalVT->isArrayTy() && 187 WebAssembly::isRefType(GlobalVT->getArrayElementType())) { 188 IsTable = true; 189 const Type *ElTy = GlobalVT->getArrayElementType(); 190 if (WebAssembly::isExternrefType(ElTy)) 191 ValTy = wasm::ValType::EXTERNREF; 192 else if (WebAssembly::isFuncrefType(ElTy)) 193 ValTy = wasm::ValType::FUNCREF; 194 else 195 report_fatal_error("unhandled reference type"); 196 } else if (VTs.size() == 1) { 197 ValTy = WebAssembly::toValType(VTs[0]); 198 } else 199 report_fatal_error("Aggregate globals not yet implemented"); 200 201 if (IsTable) { 202 Sym->setType(wasm::WASM_SYMBOL_TYPE_TABLE); 203 Sym->setTableType(ValTy); 204 } else { 205 Sym->setType(wasm::WASM_SYMBOL_TYPE_GLOBAL); 206 Sym->setGlobalType(wasm::WasmGlobalType{uint8_t(ValTy), /*Mutable=*/true}); 207 } 208 } 209