From 81db9f543ceb2f91a03ed5ce01f734f580829e47 Mon Sep 17 00:00:00 2001 From: Wouter van Oortmerssen Date: Mon, 8 Jul 2019 16:58:37 +0000 Subject: [PATCH] [WebAssembly] tablegen: distinguish float/int immediate operands. Summary: Before, they were one category of operands which could cause crashes in non-sensical combinations, e.g. "f32.const symbol". Now these are forced to be an error. Reviewers: dschuff Subscribers: sbc100, jgravelle-google, aheejin, sunfish, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D64039 llvm-svn: 365351 --- .../AsmParser/WebAssemblyAsmParser.cpp | 17 +++++++++++------ .../Target/WebAssembly/WebAssemblyInstrInfo.td | 15 +++++++++++++-- .../test/MC/WebAssembly/basic-assembly-errors.s | 4 ++++ 3 files changed, 28 insertions(+), 8 deletions(-) diff --git a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp index e22ed8e4764be1d..c7a88906019fde9 100644 --- a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp +++ b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp @@ -89,9 +89,8 @@ struct WebAssemblyOperand : public MCParsedAsmOperand { } bool isToken() const override { return Kind == Token; } - bool isImm() const override { - return Kind == Integer || Kind == Float || Kind == Symbol; - } + bool isImm() const override { return Kind == Integer || Kind == Symbol; } + bool isFPImm() const { return Kind == Float; } bool isMem() const override { return false; } bool isReg() const override { return false; } bool isBrList() const { return Kind == BrList; } @@ -118,12 +117,18 @@ struct WebAssemblyOperand : public MCParsedAsmOperand { assert(N == 1 && "Invalid number of operands!"); if (Kind == Integer) Inst.addOperand(MCOperand::createImm(Int.Val)); - else if (Kind == Float) - Inst.addOperand(MCOperand::createFPImm(Flt.Val)); else if (Kind == Symbol) Inst.addOperand(MCOperand::createExpr(Sym.Exp)); else - llvm_unreachable("Should be immediate or symbol!"); + llvm_unreachable("Should be integer immediate or symbol!"); + } + + void addFPImmOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + if (Kind == Float) + Inst.addOperand(MCOperand::createFPImm(Flt.Val)); + else + llvm_unreachable("Should be float immediate!"); } void addBrListOperands(MCInst &Inst, unsigned N) const { diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td index c42118e82c878c9..859cb9bcdfd970d 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td @@ -118,6 +118,17 @@ def WebAssemblythrow : SDNode<"WebAssemblyISD::THROW", SDT_WebAssemblyThrow, // WebAssembly-specific Operands. //===----------------------------------------------------------------------===// +// Default Operand has AsmOperandClass "Imm" which is for integers (and +// symbols), so specialize one for floats: +def FPImmAsmOperand : AsmOperandClass { + let Name = "FPImm"; + let PredicateMethod = "isFPImm"; +} + +class FPOperand : Operand { + AsmOperandClass ParserMatchClass = FPImmAsmOperand; +} + let OperandNamespace = "WebAssembly" in { let OperandType = "OPERAND_BASIC_BLOCK" in @@ -136,10 +147,10 @@ let OperandType = "OPERAND_I64IMM" in def i64imm_op : Operand; let OperandType = "OPERAND_F32IMM" in -def f32imm_op : Operand; +def f32imm_op : FPOperand; let OperandType = "OPERAND_F64IMM" in -def f64imm_op : Operand; +def f64imm_op : FPOperand; let OperandType = "OPERAND_VEC_I8IMM" in def vec_i8imm_op : Operand; diff --git a/llvm/test/MC/WebAssembly/basic-assembly-errors.s b/llvm/test/MC/WebAssembly/basic-assembly-errors.s index eead082e93f7a22..ba990f14e11a3bc 100644 --- a/llvm/test/MC/WebAssembly/basic-assembly-errors.s +++ b/llvm/test/MC/WebAssembly/basic-assembly-errors.s @@ -1,5 +1,9 @@ # RUN: not llvm-mc -triple=wasm32-unknown-unknown -mattr=+simd128,+nontrapping-fptoint,+exception-handling < %s 2>&1 | FileCheck %s +# CHECK: invalid operand for instruction +# (must be 0.0 or similar) + f32.const 0 + # CHECK: End of block construct with no start: end_try end_try test0: