diff options
Diffstat (limited to 'llvm/lib')
4 files changed, 36 insertions, 14 deletions
diff --git a/llvm/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp b/llvm/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp index 0a4227c3822..c0355aef0b3 100644 --- a/llvm/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp +++ b/llvm/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp @@ -110,7 +110,8 @@ MCDisassembler::DecodeStatus WebAssemblyDisassembler::getInstruction( MI.addOperand(MCOperand::createReg(Reg)); break; } - case WebAssembly::OPERAND_FPIMM: { + case WebAssembly::OPERAND_FP32IMM: + case WebAssembly::OPERAND_FP64IMM: { // TODO: MC converts all floating point immediate operands to double. // This is fine for numeric values, but may cause NaNs to change bits. if (Pos + sizeof(uint64_t) > Bytes.size()) diff --git a/llvm/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp b/llvm/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp index 2ecf9be2398..a58796c1ea8 100644 --- a/llvm/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp +++ b/llvm/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp @@ -110,14 +110,22 @@ void WebAssemblyInstPrinter::printInst(const MCInst *MI, raw_ostream &OS, } static std::string toString(const APFloat &FP) { + // Print NaNs with custom payloads specially. + if (FP.isNaN() && + !FP.bitwiseIsEqual(APFloat::getQNaN(FP.getSemantics())) && + !FP.bitwiseIsEqual(APFloat::getQNaN(FP.getSemantics(), /*Negative=*/true))) { + APInt AI = FP.bitcastToAPInt(); + return + std::string(AI.isNegative() ? "-" : "") + "nan:0x" + + utohexstr(AI.getZExtValue() & + (AI.getBitWidth() == 32 ? INT64_C(0x007fffff) : + INT64_C(0x000fffffffffffff)), + /*LowerCase=*/true); + } + + // Use C99's hexadecimal floating-point representation. static const size_t BufBytes = 128; char buf[BufBytes]; - if (FP.isNaN()) - assert((FP.bitwiseIsEqual(APFloat::getQNaN(FP.getSemantics())) || - FP.bitwiseIsEqual( - APFloat::getQNaN(FP.getSemantics(), /*Negative=*/true))) && - "convertToHexString handles neither SNaN nor NaN payloads"); - // Use C99's hexadecimal floating-point representation. auto Written = FP.convertToHexString( buf, /*hexDigits=*/0, /*upperCase=*/false, APFloat::rmNearestTiesToEven); (void)Written; @@ -157,10 +165,20 @@ void WebAssemblyInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, // control flow stack, and it may be nice to pretty-print. O << Op.getImm(); } else if (Op.isFPImm()) { - assert((OpNo < MII.get(MI->getOpcode()).getNumOperands() || - MII.get(MI->getOpcode()).TSFlags == 0) && + 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"); - O << toString(APFloat(Op.getFPImm())); + const MCOperandInfo &Info = Desc.OpInfo[OpNo]; + if (Info.OperandType == WebAssembly::OPERAND_FP32IMM) { + // TODO: MC converts all floating point immediate operands to double. + // This is fine for numeric values, but may cause NaNs to change bits. + O << toString(APFloat(float(Op.getFPImm()))); + } else { + assert(Info.OperandType == WebAssembly::OPERAND_FP64IMM); + O << toString(APFloat(Op.getFPImm())); + } } else { assert((OpNo < MII.get(MI->getOpcode()).getNumOperands() || (MII.get(MI->getOpcode()).TSFlags & diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h index af970929bfa..001bd7f1fc4 100644 --- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h +++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h @@ -44,8 +44,10 @@ namespace WebAssembly { enum OperandType { /// Basic block label in a branch construct. OPERAND_BASIC_BLOCK = MCOI::OPERAND_FIRST_TARGET, - /// Floating-point immediate. - OPERAND_FPIMM, + /// 32-bit floating-point immediates. + OPERAND_FP32IMM, + /// 64-bit floating-point immediates. + OPERAND_FP64IMM, /// p2align immediate for load and store address alignment. OPERAND_P2ALIGN }; diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td index 60e5d6ea645..115e532b5a2 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td @@ -71,10 +71,11 @@ let OperandNamespace = "WebAssembly" in { let OperandType = "OPERAND_BASIC_BLOCK" in def bb_op : Operand<OtherVT>; -let OperandType = "OPERAND_FPIMM" in { +let OperandType = "OPERAND_FP32IMM" in def f32imm_op : Operand<f32>; + +let OperandType = "OPERAND_FP64IMM" in def f64imm_op : Operand<f64>; -} // OperandType = "OPERAND_FPIMM" let OperandType = "OPERAND_P2ALIGN" in { def P2Align : Operand<i32> { |