| 
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