|
15 | 15 | #include "WebAssemblyMCInstLower.h" |
16 | 16 | #include "MCTargetDesc/WebAssemblyMCAsmInfo.h" |
17 | 17 | #include "MCTargetDesc/WebAssemblyMCTargetDesc.h" |
| 18 | +#include "MCTargetDesc/WebAssemblyMCTypeUtilities.h" |
18 | 19 | #include "TargetInfo/WebAssemblyTargetInfo.h" |
19 | 20 | #include "Utils/WebAssemblyTypeUtilities.h" |
20 | 21 | #include "WebAssemblyAsmPrinter.h" |
21 | 22 | #include "WebAssemblyMachineFunctionInfo.h" |
22 | 23 | #include "WebAssemblyUtilities.h" |
| 24 | +#include "llvm/ADT/SmallVector.h" |
| 25 | +#include "llvm/BinaryFormat/Wasm.h" |
23 | 26 | #include "llvm/CodeGen/AsmPrinter.h" |
24 | 27 | #include "llvm/CodeGen/MachineFunction.h" |
| 28 | +#include "llvm/CodeGen/MachineOperand.h" |
25 | 29 | #include "llvm/IR/Constants.h" |
26 | 30 | #include "llvm/MC/MCAsmInfo.h" |
27 | 31 | #include "llvm/MC/MCContext.h" |
@@ -196,11 +200,80 @@ void WebAssemblyMCInstLower::lower(const MachineInstr *MI, |
196 | 200 | MCOp = MCOperand::createReg(WAReg); |
197 | 201 | break; |
198 | 202 | } |
| 203 | + case llvm::MachineOperand::MO_CImmediate: { |
| 204 | + // Lower type index placeholder for ref.test |
| 205 | + // Currently this is the only way that CImmediates show up so panic if we |
| 206 | + // get confused. |
| 207 | + unsigned DescIndex = I - NumVariadicDefs; |
| 208 | + if (DescIndex >= Desc.NumOperands) { |
| 209 | + llvm_unreachable("unexpected CImmediate operand"); |
| 210 | + } |
| 211 | + const MCOperandInfo &Info = Desc.operands()[DescIndex]; |
| 212 | + if (Info.OperandType != WebAssembly::OPERAND_TYPEINDEX) { |
| 213 | + llvm_unreachable("unexpected CImmediate operand"); |
| 214 | + } |
| 215 | + auto CImm = MO.getCImm()->getValue(); |
| 216 | + auto NumWords = CImm.getNumWords(); |
| 217 | + // Extract the type data we packed into the CImm in LowerRefTestFuncRef. |
| 218 | + // We need to load the words from most significant to least significant |
| 219 | + // order because of the way we bitshifted them in from the right. |
| 220 | + // The return type needs special handling because it could be void. |
| 221 | + auto ReturnType = static_cast<WebAssembly::BlockType>( |
| 222 | + CImm.extractBitsAsZExtValue(64, (NumWords - 1) * 64)); |
| 223 | + SmallVector<wasm::ValType, 2> Returns; |
| 224 | + switch (ReturnType) { |
| 225 | + case WebAssembly::BlockType::Invalid: |
| 226 | + llvm_unreachable("Invalid return type"); |
| 227 | + case WebAssembly::BlockType::I32: |
| 228 | + Returns = {wasm::ValType::I32}; |
| 229 | + break; |
| 230 | + case WebAssembly::BlockType::I64: |
| 231 | + Returns = {wasm::ValType::I64}; |
| 232 | + break; |
| 233 | + case WebAssembly::BlockType::F32: |
| 234 | + Returns = {wasm::ValType::F32}; |
| 235 | + break; |
| 236 | + case WebAssembly::BlockType::F64: |
| 237 | + Returns = {wasm::ValType::F64}; |
| 238 | + break; |
| 239 | + case WebAssembly::BlockType::Void: |
| 240 | + Returns = {}; |
| 241 | + break; |
| 242 | + case WebAssembly::BlockType::Exnref: |
| 243 | + Returns = {wasm::ValType::EXNREF}; |
| 244 | + break; |
| 245 | + case WebAssembly::BlockType::Externref: |
| 246 | + Returns = {wasm::ValType::EXTERNREF}; |
| 247 | + break; |
| 248 | + case WebAssembly::BlockType::Funcref: |
| 249 | + Returns = {wasm::ValType::FUNCREF}; |
| 250 | + break; |
| 251 | + case WebAssembly::BlockType::V128: |
| 252 | + Returns = {wasm::ValType::V128}; |
| 253 | + break; |
| 254 | + case WebAssembly::BlockType::Multivalue: { |
| 255 | + llvm_unreachable("Invalid return type"); |
| 256 | + } |
| 257 | + } |
| 258 | + SmallVector<wasm::ValType, 4> Params; |
| 259 | + |
| 260 | + for (int I = NumWords - 2; I >= 0; I--) { |
| 261 | + auto Val = CImm.extractBitsAsZExtValue(64, 64 * I); |
| 262 | + auto ParamType = static_cast<wasm::ValType>(Val); |
| 263 | + Params.push_back(ParamType); |
| 264 | + } |
| 265 | + MCOp = lowerTypeIndexOperand(std::move(Returns), std::move(Params)); |
| 266 | + break; |
| 267 | + } |
199 | 268 | case MachineOperand::MO_Immediate: { |
200 | 269 | unsigned DescIndex = I - NumVariadicDefs; |
201 | 270 | if (DescIndex < Desc.NumOperands) { |
202 | 271 | const MCOperandInfo &Info = Desc.operands()[DescIndex]; |
| 272 | + // Replace type index placeholder with actual type index. The type index |
| 273 | + // placeholders are Immediates and have an operand type of |
| 274 | + // OPERAND_TYPEINDEX or OPERAND_SIGNATURE. |
203 | 275 | if (Info.OperandType == WebAssembly::OPERAND_TYPEINDEX) { |
| 276 | + // Lower type index placeholder for a CALL_INDIRECT instruction |
204 | 277 | SmallVector<wasm::ValType, 4> Returns; |
205 | 278 | SmallVector<wasm::ValType, 4> Params; |
206 | 279 |
|
@@ -228,6 +301,7 @@ void WebAssemblyMCInstLower::lower(const MachineInstr *MI, |
228 | 301 | break; |
229 | 302 | } |
230 | 303 | if (Info.OperandType == WebAssembly::OPERAND_SIGNATURE) { |
| 304 | + // Lower type index placeholder for blocks |
231 | 305 | auto BT = static_cast<WebAssembly::BlockType>(MO.getImm()); |
232 | 306 | assert(BT != WebAssembly::BlockType::Invalid); |
233 | 307 | if (BT == WebAssembly::BlockType::Multivalue) { |
|
0 commit comments