Currently, the asm parser stops matching instruction operands as soon as the first optional operand is encountered. This leads to the need for custom checks on missing mandatory operands that come after optional operands.
The patch changes the parser to always match all optional and mandatory instruction operands, thus making the custom checks unnecessary. This is particularly useful for the AMDGPU backend where we have numerous optional instruction modifiers.
Reviewed By: dp
Differential Revision: https://reviews.llvm.org/D137549
// RUN: not llvm-mc -arch=amdgcn -mcpu=gfx1010 -mattr=+WavefrontSize32,-WavefrontSize64 %s 2>&1 | FileCheck %s --implicit-check-not=error: --strict-whitespace
//==============================================================================
-// dim modifier is required on this GPU
+// operands are not valid for this GPU or mode
image_atomic_add v252, v2, s[8:15]
-// CHECK: error: dim modifier is required on this GPU
+// CHECK: error: operands are not valid for this GPU or mode
// CHECK-NEXT:{{^}}image_atomic_add v252, v2, s[8:15]
// CHECK-NEXT:{{^}}^
// CHECK-NEXT:{{^}} ^
//==============================================================================
-// missing dst operand or lds modifier
-
-buffer_load_dword off, s[8:11], s3
-// CHECK: error: missing dst operand or lds modifier
-// CHECK-NEXT:{{^}}buffer_load_dword off, s[8:11], s3
-// CHECK-NEXT:{{^}}^
-
-buffer_load_dword off, s[8:11], s3 offset:1
-// CHECK: error: missing dst operand or lds modifier
-// CHECK-NEXT:{{^}}buffer_load_dword off, s[8:11], s3 offset:1
-// CHECK-NEXT:{{^}}^
-
-//==============================================================================
// missing message operation
s_sendmsg sendmsg(MSG_SYSMSG)
// CHECK-NEXT:{{^}}v_add_f32_e64 v0, v1
// CHECK-NEXT:{{^}}^
+buffer_load_dword off, s[8:11], s3
+// CHECK: error: too few operands for instruction
+// CHECK-NEXT:{{^}}buffer_load_dword off, s[8:11], s3
+// CHECK-NEXT:{{^}}^
+
+buffer_load_dword off, s[8:11], s3 offset:1
+// CHECK: error: too few operands for instruction
+// CHECK-NEXT:{{^}}buffer_load_dword off, s[8:11], s3 offset:1
+// CHECK-NEXT:{{^}}^
+
//==============================================================================
// too large value for expcnt
// GFX9ERR: error: instruction not supported on this GPU
global_load_dword v[2:3], off
-// GFX9ERR: error: missing dst operand or lds modifier
+// GFX9ERR: error: too few operands for instruction
scratch_load_dword v2, off, offset:256
-// GFX9ERR: error: missing dst operand or lds modifier
+// GFX9ERR: error: too few operands for instruction
// CHECK-NEXT:{{^}} ^
//==============================================================================
-// missing dst operand or lds modifier
+// too few operands for instruction
buffer_load_dword off, s[8:11], s3
-// CHECK: error: missing dst operand or lds modifier
+// CHECK: error: too few operands for instruction
// CHECK-NEXT:{{^}}buffer_load_dword off, s[8:11], s3
// CHECK-NEXT:{{^}}^
buffer_load_dword off, s[8:11], s3 offset:1
-// CHECK: error: missing dst operand or lds modifier
+// CHECK: error: too few operands for instruction
// CHECK-NEXT:{{^}}buffer_load_dword off, s[8:11], s3 offset:1
// CHECK-NEXT:{{^}}^
// NOVI: error: invalid operand for instruction
buffer_load_dword off, s[8:11], s3
-// NOSICIVI: error: missing dst operand or lds modifier
+// NOSICIVI: error: too few operands for instruction
buffer_load_dword off, s[8:11], s3 offset:1
-// NOSICIVI: error: missing dst operand or lds modifier
+// NOSICIVI: error: too few operands for instruction
// CHECK: Matching formal operand class MCK_GR64 against actual operand at index 1 (Reg:r3): match success using generic matcher
// CHECK: Matching formal operand class MCK_GR64 against actual operand at index 2 (Reg:r0): match success using generic matcher
// CHECK: Matching formal operand class MCK_BDAddr32Disp20 against actual operand at index 3 (Mem:3): match success using generic matcher
-// CHECK: Matching formal operand class InvalidMatchClass against actual operand at index 4: actual operand index out of range Opcode result: complete match, selecting this opcode
+// CHECK: Matching formal operand class InvalidMatchClass against actual operand at index 4: actual operand index out of range
+// CHECK: Opcode result: complete match, selecting this opcode
// CHECK: AsmMatcher: found 1 encodings with mnemonic 'llill'
// CHECK: Trying to match opcode LLILL
// CHECK: Matching formal operand class MCK_GR64 against actual operand at index 1 (Reg:r0): match success using generic matcher
// CHECK: Matching formal operand class MCK_U16Imm against actual operand at index 2 (Imm:0): match success using generic matcher
-// CHECK: Matching formal operand class InvalidMatchClass against actual operand at index 3: actual operand index out of range Opcode result: complete match, selecting this opcode
+// CHECK: Matching formal operand class InvalidMatchClass against actual operand at index 3: actual operand index out of range
+// CHECK: Opcode result: complete match, selecting this opcode
// CHECK: AsmMatcher: found 1 encodings with mnemonic 'lgr'
// CHECK: Trying to match opcode LGR
// CHECK: Matching formal operand class MCK_GR64 against actual operand at index 1 (Reg:r1): match success using generic matcher
// CHECK: Matching formal operand class MCK_GR64 against actual operand at index 2 (Reg:r0): match success using generic matcher
-// CHECK: Matching formal operand class InvalidMatchClass against actual operand at index 3: actual operand index out of range Opcode result: complete match, selecting this opcode
+// CHECK: Matching formal operand class InvalidMatchClass against actual operand at index 3: actual operand index out of range
+// CHECK: Opcode result: complete match, selecting this opcode
// CHECK: AsmMatcher: found 1 encodings with mnemonic 'lg'
// CHECK: Trying to match opcode LG
// CHECK: Matching formal operand class MCK_GR64 against actual operand at index 1 (Reg:r1): match success using generic matcher
// CHECK: Matching formal operand class MCK_BDXAddr64Disp20 against actual operand at index 2 (Mem:16(r2)): match success using generic matcher
-// CHECK: Matching formal operand class InvalidMatchClass against actual operand at index 3: actual operand index out of range Opcode result: complete match, selecting this opcode
+// CHECK: Matching formal operand class InvalidMatchClass against actual operand at index 3: actual operand index out of range
+// CHECK: Opcode result: complete match, selecting this opcode
// CHECK: AsmMatcher: found 1 encodings with mnemonic 'lg'
// CHECK: Trying to match opcode LG
// CHECK: Matching formal operand class MCK_GR64 against actual operand at index 1 (Reg:r1): match success using generic matcher
// CHECK: Matching formal operand class MCK_BDXAddr64Disp20 against actual operand at index 2 (Mem:16(r2,r3)): match success using generic matcher
-// CHECK: Matching formal operand class InvalidMatchClass against actual operand at index 3: actual operand index out of range Opcode result: complete match, selecting this opcode
+// CHECK: Matching formal operand class InvalidMatchClass against actual operand at index 3: actual operand index out of range
+// CHECK: Opcode result: complete match, selecting this opcode
// CHECK: AsmMatcher: found 1 encodings with mnemonic 'stmg'
// CHECK: Trying to match opcode STMG
// CHECK: Matching formal operand class MCK_GR64 against actual operand at index 1 (Reg:r13): match success using generic matcher
// CHECK: Matching formal operand class MCK_GR64 against actual operand at index 2 (Reg:r15): match success using generic matcher
// CHECK: Matching formal operand class MCK_BDAddr64Disp20 against actual operand at index 3 (Mem:104(r15)): match success using generic matcher
-// CHECK: Matching formal operand class InvalidMatchClass against actual operand at index 4: actual operand index out of range Opcode result: complete match, selecting this opcode
+// CHECK: Matching formal operand class InvalidMatchClass against actual operand at index 4: actual operand index out of range
+// CHECK: Opcode result: complete match, selecting this opcode
// CHECK: AsmMatcher: found 1 encodings with mnemonic 'mvc'
// CHECK: Trying to match opcode MVC
// CHECK: Matching formal operand class MCK_BDLAddr64Disp12Len8 against actual operand at index 1 (Mem:184(8,r15)): match success using generic matcher
// CHECK: Matching formal operand class MCK_BDAddr64Disp12 against actual operand at index 2 (Mem:8(r2)): match success using generic matcher
-// CHECK: Matching formal operand class InvalidMatchClass against actual operand at index 3: actual operand index out of range Opcode result: complete match, selecting this opcode
+// CHECK: Matching formal operand class InvalidMatchClass against actual operand at index 3: actual operand index out of range
+// CHECK: Opcode result: complete match, selecting this opcode
// CHECK: AsmMatcher: found 1 encodings with mnemonic 'mvck'
// CHECK: Trying to match opcode MVCK
// CHECK: Matching formal operand class MCK_BDRAddr64Disp12 against actual operand at index 1 (Mem:0(r0,r1)): match success using generic matcher
// CHECK: Matching formal operand class MCK_BDAddr64Disp12 against actual operand at index 2 (Mem:4095(r15)): match success using generic matcher
// CHECK: Matching formal operand class MCK_GR64 against actual operand at index 3 (Reg:r2): match success using generic matcher
-// CHECK: Matching formal operand class InvalidMatchClass against actual operand at index 4: actual operand index out of range Opcode result: complete match, selecting this opcode
+// CHECK: Matching formal operand class InvalidMatchClass against actual operand at index 4: actual operand index out of range
+// CHECK: Opcode result: complete match, selecting this opcode
// CHECK: AsmMatcher: found 1 encodings with mnemonic 'j'
// CHECK: Trying to match opcode J
// CHECK: Matching formal operand class MCK_PCRel16 against actual operand at index 1 (Imm:.Ltmp0+2): match success using generic matcher
-// CHECK: Matching formal operand class InvalidMatchClass against actual operand at index 2: actual operand index out of range Opcode result: complete match, selecting this opcode
+// CHECK: Matching formal operand class InvalidMatchClass against actual operand at index 2: actual operand index out of range
+// CHECK: Opcode result: complete match, selecting this opcode
// CHECK: AsmMatcher: found 1 encodings with mnemonic 'brasl'
// CHECK: Trying to match opcode BRASL
// CHECK: Matching formal operand class MCK_GR64 against actual operand at index 1 (Reg:r14): match success using generic matcher
// CHECK: Matching formal operand class MCK_PCRelTLS32 against actual operand at index 2 (ImmTLS:fun): match success using generic matcher
-// CHECK: Matching formal operand class InvalidMatchClass against actual operand at index 3: actual operand index out of range Opcode result: complete match, selecting this opcode
+// CHECK: Matching formal operand class InvalidMatchClass against actual operand at index 3: actual operand index out of range
+// CHECK: Opcode result: complete match, selecting this opcode
// CHECK: .text
// CHECK: sllg %r3, %r0, 3
// CHECK: llill %r0, 0
// CHECK: Trying to match opcode PSHUFBrm
// CHECK: Matching formal operand class MCK_Mem128 against actual operand at index 1 (Memory: ModeSize=64,BaseReg=rip,Scale=1,Disp=CPI1_0): match success using generic matcher
// CHECK: Matching formal operand class MCK_FR16 against actual operand at index 2 (Reg:xmm1): match success using generic matcher
-// CHECK: Matching formal operand class InvalidMatchClass against actual operand at index 3: actual operand index out of range Opcode result: complete match, selecting this opcode
+// CHECK: Matching formal operand class InvalidMatchClass against actual operand at index 3: actual operand index out of range
+// CHECK: Opcode result: complete match, selecting this opcode
// CHECK: AsmMatcher: found 2 encodings with mnemonic 'sha1rnds4'
// CHECK: Trying to match opcode SHA1RNDS4rri
// CHECK: Matching formal operand class MCK_ImmUnsignedi8 against actual operand at index 1 (Imm:1): match success using generic matcher
// CHECK: Matching formal operand class MCK_FR16 against actual operand at index 2 (Reg:xmm1): match success using generic matcher
// CHECK: Matching formal operand class MCK_FR16 against actual operand at index 3 (Reg:xmm2): match success using generic matcher
-// CHECK: Matching formal operand class InvalidMatchClass against actual operand at index 4: actual operand index out of range Opcode result: complete match, selecting this opcode
+// CHECK: Matching formal operand class InvalidMatchClass against actual operand at index 4: actual operand index out of range
+// CHECK: Opcode result: complete match, selecting this opcode
// CHECK: AsmMatcher: found 4 encodings with mnemonic 'pinsrw'
// CHECK: Trying to match opcode MMX_PINSRWrr
// CHECK: Matching formal operand class MCK_ImmUnsignedi8 against actual operand at index 1 (Imm:3): match success using generic matcher
// CHECK: Matching formal operand class MCK_ImmUnsignedi8 against actual operand at index 1 (Imm:3): match success using generic matcher
// CHECK: Matching formal operand class MCK_GR32orGR64 against actual operand at index 2 (Reg:ecx): match success using generic matcher
// CHECK: Matching formal operand class MCK_FR16 against actual operand at index 3 (Reg:xmm5): match success using generic matcher
-// CHECK: Matching formal operand class InvalidMatchClass against actual operand at index 4: actual operand index out of range Opcode result: complete match, selecting this opcode
+// CHECK: Matching formal operand class InvalidMatchClass against actual operand at index 4: actual operand index out of range
+// CHECK: Opcode result: complete match, selecting this opcode
// CHECK: AsmMatcher: found 2 encodings with mnemonic 'crc32l'
// CHECK: Trying to match opcode CRC32r32r32
// CHECK: Matching formal operand class MCK_GR32 against actual operand at index 1 (Memory: ModeSize=64,BaseReg=rbx,IndexReg=rcx,Scale=8,Disp=3735928559,SegReg=gs): Opcode result: multiple operand mismatches, ignoring this opcode
// CHECK: Trying to match opcode CRC32r32m32
// CHECK: Matching formal operand class MCK_Mem32 against actual operand at index 1 (Memory: ModeSize=64,BaseReg=rbx,IndexReg=rcx,Scale=8,Disp=3735928559,SegReg=gs): match success using generic matcher
// CHECK: Matching formal operand class MCK_GR32 against actual operand at index 2 (Reg:ecx): match success using generic matcher
-// CHECK: Matching formal operand class InvalidMatchClass against actual operand at index 3: actual operand index out of range Opcode result: complete match, selecting this opcode
+// CHECK: Matching formal operand class InvalidMatchClass against actual operand at index 3: actual operand index out of range
+// CHECK: Opcode result: complete match, selecting this opcode
// CHECK: AsmMatcher: found 4 encodings with mnemonic 'punpcklbw'
// CHECK: Trying to match opcode MMX_PUNPCKLBWrr
// CHECK: Matching formal operand class MCK_VR64 against actual operand at index 1 (Reg:mm0): match success using generic matcher
// CHECK: Trying to match opcode MMX_PUNPCKLBWrm
// CHECK: Matching formal operand class MCK_VR64 against actual operand at index 1 (Reg:mm0): match success using generic matcher
// CHECK: Matching formal operand class MCK_Mem32 against actual operand at index 2 (Memory: ModeSize=64,Size=32,BaseReg=rsp,Scale=1): match success using generic matcher
-// CHECK: Matching formal operand class InvalidMatchClass against actual operand at index 3: actual operand index out of range Opcode result: complete match, selecting this opcode
+// CHECK: Matching formal operand class InvalidMatchClass against actual operand at index 3: actual operand index out of range
+// CHECK: Opcode result: complete match, selecting this opcode
pshufb CPI1_0(%rip), %xmm1
sha1rnds4 $1, %xmm1, %xmm2
OS << " else\n";
OS << " DEBUG_WITH_TYPE(\"asm-matcher\", dbgs() << \": \");\n";
OS << " if (ActualIdx >= Operands.size()) {\n";
- OS << " DEBUG_WITH_TYPE(\"asm-matcher\", dbgs() << \"actual operand index out of range \");\n";
+ OS << " DEBUG_WITH_TYPE(\"asm-matcher\", dbgs() << \"actual operand "
+ "index out of range\\n\");\n";
if (ReportMultipleNearMisses) {
OS << " bool ThisOperandValid = (Formal == " <<"InvalidMatchClass) || "
"isSubclass(Formal, OptionalMatchClass);\n";
OS << " }\n";
OS << " continue;\n";
} else {
- OS << " OperandsValid = (Formal == InvalidMatchClass) || isSubclass(Formal, OptionalMatchClass);\n";
- OS << " if (!OperandsValid) ErrorInfo = ActualIdx;\n";
+ OS << " if (Formal == InvalidMatchClass) {\n";
if (HasOptionalOperands) {
- OS << " OptionalOperandsMask.set(FormalIdx, " << MaxNumOperands
+ OS << " OptionalOperandsMask.set(FormalIdx, " << MaxNumOperands
<< ");\n";
}
+ OS << " break;\n";
+ OS << " }\n";
+ OS << " if (isSubclass(Formal, OptionalMatchClass)) {\n";
+ if (HasOptionalOperands) {
+ OS << " OptionalOperandsMask.set(FormalIdx);\n";
+ }
+ OS << " continue;\n";
+ OS << " }\n";
+ OS << " OperandsValid = false;\n";
+ OS << " ErrorInfo = ActualIdx;\n";
OS << " break;\n";
}
OS << " }\n";