diff options
author | Wouter van Oortmerssen <aardappel@gmail.com> | 2018-12-17 22:04:44 +0000 |
---|---|---|
committer | Wouter van Oortmerssen <aardappel@gmail.com> | 2018-12-17 22:04:44 +0000 |
commit | d3c544aa6ec94aaf143a092cbd1058890863c7dc (patch) | |
tree | 7ef64c5f8edde9082a3382f14c783dc7a6aa380d /llvm/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp | |
parent | 8c9d7729916c143fac07ea69acfff3cb13458278 (diff) | |
download | bcm5719-llvm-d3c544aa6ec94aaf143a092cbd1058890863c7dc.tar.gz bcm5719-llvm-d3c544aa6ec94aaf143a092cbd1058890863c7dc.zip |
[WebAssembly] Fix assembler parsing of br_table.
Summary:
We use `variable_ops` in the tablegen defs to denote the list of
branch targets in `br_table`, but unlike other uses of `variable_ops`
(e.g. call) the these branch targets need to actually be encoded in the
instruction. The existing tables for `variable_ops` cause not operands
to be accepted by the assembly matcher.
Following the example of ARM:
https://github.com/llvm-mirror/llvm/blob/2cc0a7da876c1d8c32775b0119e1e15aaa759b9e/lib/Target/ARM/ARMInstrInfo.td#L550-L555
we introduce a new operand type to capture this list, and we use the
same {} syntax as ARM as well to differentiate them from regular
integer operands.
Also removed definition and use of TSFlags in tablegen defs, since
`br_table` now has a non-variable_ops immediate operand, so the
previous logic of only the variable_ops arguments being labels didn't
make sense anymore.
Reviewers: dschuff, aheejin, sunfish
Subscribers: javed.absar, sbc100, jgravelle-google, kristof.beyls, llvm-commits
Differential Revision: https://reviews.llvm.org/D55401
llvm-svn: 349405
Diffstat (limited to 'llvm/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp')
-rw-r--r-- | llvm/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp | 51 |
1 files changed, 24 insertions, 27 deletions
diff --git a/llvm/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp b/llvm/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp index e94faa1a214..eaf9750792b 100644 --- a/llvm/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp +++ b/llvm/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp @@ -134,11 +134,19 @@ void WebAssemblyInstPrinter::printInst(const MCInst *MI, raw_ostream &OS, unsigned NumFixedOperands = Desc.NumOperands; SmallSet<uint64_t, 8> Printed; for (unsigned i = 0, e = MI->getNumOperands(); i < e; ++i) { - if (!(i < NumFixedOperands - ? (Desc.OpInfo[i].OperandType == - WebAssembly::OPERAND_BASIC_BLOCK) - : (Desc.TSFlags & WebAssemblyII::VariableOpImmediateIsLabel))) - continue; + // See if this operand denotes a basic block target. + if (i < NumFixedOperands) { + // A non-variable_ops operand, check its type. + if (Desc.OpInfo[i].OperandType != WebAssembly::OPERAND_BASIC_BLOCK) + continue; + } else { + // A variable_ops operand, which currently can be immediates (used in + // br_table) which are basic block targets, or for call instructions + // when using -wasm-keep-registers (in which case they are registers, + // and should not be processed). + if (!MI->getOperand(i).isImm()) + continue; + } uint64_t Depth = MI->getOperand(i).getImm(); if (!Printed.insert(Depth).second) continue; @@ -194,9 +202,6 @@ void WebAssemblyInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O) { const MCOperand &Op = MI->getOperand(OpNo); if (Op.isReg()) { - assert((OpNo < MII.get(MI->getOpcode()).getNumOperands() || - MII.get(MI->getOpcode()).TSFlags == 0) && - "WebAssembly variable_ops register ops don't use TSFlags"); unsigned WAReg = Op.getReg(); if (int(WAReg) >= 0) printRegName(O, WAReg); @@ -210,23 +215,9 @@ void WebAssemblyInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, if (OpNo < MII.get(MI->getOpcode()).getNumDefs()) O << '='; } else if (Op.isImm()) { - const MCInstrDesc &Desc = MII.get(MI->getOpcode()); - assert((OpNo < Desc.getNumOperands() || - (Desc.TSFlags & WebAssemblyII::VariableOpIsImmediate)) && - "WebAssemblyII::VariableOpIsImmediate should be set for " - "variable_ops immediate ops"); - (void)Desc; - // TODO: (MII.get(MI->getOpcode()).TSFlags & - // WebAssemblyII::VariableOpImmediateIsLabel) - // can tell us whether this is an immediate referencing a label in the - // control flow stack, and it may be nice to pretty-print. O << Op.getImm(); } else if (Op.isFPImm()) { const MCInstrDesc &Desc = MII.get(MI->getOpcode()); - assert(OpNo < Desc.getNumOperands() && - "Unexpected floating-point immediate as a non-fixed operand"); - assert(Desc.TSFlags == 0 && - "WebAssembly variable_ops floating point ops don't use TSFlags"); const MCOperandInfo &Info = Desc.OpInfo[OpNo]; if (Info.OperandType == WebAssembly::OPERAND_F32IMM) { // TODO: MC converts all floating point immediate operands to double. @@ -237,16 +228,22 @@ void WebAssemblyInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, O << ::toString(APFloat(Op.getFPImm())); } } else { - assert((OpNo < MII.get(MI->getOpcode()).getNumOperands() || - (MII.get(MI->getOpcode()).TSFlags & - WebAssemblyII::VariableOpIsImmediate)) && - "WebAssemblyII::VariableOpIsImmediate should be set for " - "variable_ops expr ops"); assert(Op.isExpr() && "unknown operand kind in printOperand"); Op.getExpr()->print(O, &MAI); } } +void WebAssemblyInstPrinter::printBrList(const MCInst *MI, unsigned OpNo, + raw_ostream &O) { + O << "{"; + for (unsigned I = OpNo, E = MI->getNumOperands(); I != E; ++I) { + if (I != OpNo) + O << ", "; + O << MI->getOperand(I).getImm(); + } + O << "}"; +} + void WebAssemblyInstPrinter::printWebAssemblyP2AlignOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O) { |