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