Index: lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp =================================================================== --- lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp +++ lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp @@ -151,7 +151,8 @@ MI.setOpcode(WasmInst->Opcode); // Parse any operands. for (uint8_t OPI = 0; OPI < WasmInst->NumOperands; OPI++) { - switch (OperandTable[WasmInst->OperandStart + OPI]) { + auto OT = OperandTable[WasmInst->OperandStart + OPI]; + switch (OT) { // ULEB operands: case WebAssembly::OPERAND_BASIC_BLOCK: case WebAssembly::OPERAND_LOCAL: @@ -210,6 +211,19 @@ return MCDisassembler::Fail; break; } + case WebAssembly::OPERAND_BRLIST: { + int64_t TargetTableLen; + if (!nextLEB(TargetTableLen, Bytes, Size, false)) + return MCDisassembler::Fail; + for (int64_t I = 0; I < TargetTableLen; I++) { + if (!parseLEBImmediate(MI, Size, Bytes, false)) + return MCDisassembler::Fail; + } + // Default case. + if (!parseLEBImmediate(MI, Size, Bytes, false)) + return MCDisassembler::Fail; + break; + } case MCOI::OPERAND_REGISTER: // The tablegen header currently does not have any register operands since // we use only the stack (_S) instructions. Index: lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h =================================================================== --- lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h +++ lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h @@ -79,6 +79,8 @@ OPERAND_TYPEINDEX, /// Event index. OPERAND_EVENT, + /// A list of branch targets for br_list. + OPERAND_BRLIST, }; } // end namespace WebAssembly Index: lib/Target/WebAssembly/WebAssemblyInstrControl.td =================================================================== --- lib/Target/WebAssembly/WebAssemblyInstrControl.td +++ lib/Target/WebAssembly/WebAssemblyInstrControl.td @@ -36,10 +36,14 @@ // A list of branch targets enclosed in {} and separated by comma. // Used by br_table only. def BrListAsmOperand : AsmOperandClass { let Name = "BrList"; } +let OperandNamespace = "WebAssembly" in { +let OperandType = "OPERAND_BRLIST" in { def brlist : Operand { let ParserMatchClass = BrListAsmOperand; let PrintMethod = "printBrList"; } +} // OPERAND_BRLIST +} // OperandNamespace = "WebAssembly" // TODO: SelectionDAG's lowering insists on using a pointer as the index for // jump tables, so in practice we don't ever use BR_TABLE_I64 in wasm32 mode Index: test/MC/Disassembler/WebAssembly/wasm.txt =================================================================== --- test/MC/Disassembler/WebAssembly/wasm.txt +++ test/MC/Disassembler/WebAssembly/wasm.txt @@ -44,3 +44,7 @@ # CHECK: i64x2.any_true # CHECK-NOT: i64.div_u 0xFD 0x85 0x81 0x80 0x80 0x80 0x80 0x00 + +# Check br_table, which has its own operand type. +# CHECK: br_table {0, 1, 2} +0x0E 0x02 0x00 0x01 0x02 Index: utils/TableGen/WebAssemblyDisassemblerEmitter.cpp =================================================================== --- utils/TableGen/WebAssemblyDisassemblerEmitter.cpp +++ utils/TableGen/WebAssemblyDisassemblerEmitter.cpp @@ -92,6 +92,7 @@ // Collect operand types for storage in a shared list. CurOperandList.clear(); for (auto &Op : CGI.Operands.OperandList) { + assert(Op.OperandType != "MCOI::OPERAND_UNKNOWN"); CurOperandList.push_back(Op.OperandType); } // See if we already have stored this sequence before. This is not