From e1de2773a534957305d7a559c6d88c4b5ac354e2 Mon Sep 17 00:00:00 2001 From: Ulrich Weigand Date: Wed, 29 Apr 2020 19:59:50 +0200 Subject: [PATCH] [SystemZ] Allow specifying plain register numbers in AsmParser For compatibility with other assemblers on the platform, allow using just plain integer register numbers in all places where a register operand is expected. Bug: llvm.org/PR45582 --- .../Target/SystemZ/AsmParser/SystemZAsmParser.cpp | 119 ++++++++++++++------- llvm/test/MC/SystemZ/regs-bad.s | 60 +++++------ llvm/test/MC/SystemZ/regs-good.s | 16 +++ 3 files changed, 126 insertions(+), 69 deletions(-) diff --git a/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp b/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp index b6c2f83..a311024 100644 --- a/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp +++ b/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp @@ -748,45 +748,86 @@ bool SystemZAsmParser::parseRegister(Register &Reg, bool RestoreOnFailure) { // Parse a register of kind Kind and add it to Operands. OperandMatchResultTy SystemZAsmParser::parseRegister(OperandVector &Operands, RegisterKind Kind) { - if (Parser.getTok().isNot(AsmToken::Percent)) - return MatchOperand_NoMatch; + SMLoc StartLoc, EndLoc; + unsigned RegNum; - Register Reg; - if (parseRegister(Reg)) - return MatchOperand_ParseFail; + // Handle register names of the form %. + if (Parser.getTok().is(AsmToken::Percent)) { + Register Reg; + if (parseRegister(Reg)) + return MatchOperand_ParseFail; - // Verify that a register prefix appropriate for Kind was used. - bool PrefixMatch; - switch (Kind) { - case GR32Reg: - case GRH32Reg: - case GR64Reg: - case GR128Reg: - PrefixMatch = Reg.Group == RegGR; - break; - case FP32Reg: - case FP64Reg: - case FP128Reg: - PrefixMatch = Reg.Group == RegFP; - break; - case VR32Reg: - case VR64Reg: - case VR128Reg: - // It is OK to use the %f prefix with vector instructions that - // expect some VR..Reg kind, so accept the RegFP group as well. - PrefixMatch = Reg.Group == RegV || Reg.Group == RegFP; - break; - case AR32Reg: - PrefixMatch = Reg.Group == RegAR; - break; - case CR64Reg: - PrefixMatch = Reg.Group == RegCR; - break; + // Verify that a register prefix appropriate for Kind was used. + bool PrefixMatch; + switch (Kind) { + case GR32Reg: + case GRH32Reg: + case GR64Reg: + case GR128Reg: + PrefixMatch = Reg.Group == RegGR; + break; + case FP32Reg: + case FP64Reg: + case FP128Reg: + PrefixMatch = Reg.Group == RegFP; + break; + case VR32Reg: + case VR64Reg: + case VR128Reg: + // It is OK to use the %f prefix with vector instructions that + // expect some VR..Reg kind, so accept the RegFP group as well. + PrefixMatch = Reg.Group == RegV || Reg.Group == RegFP; + break; + case AR32Reg: + PrefixMatch = Reg.Group == RegAR; + break; + case CR64Reg: + PrefixMatch = Reg.Group == RegCR; + break; + } + if (!PrefixMatch) { + Error(Reg.StartLoc, "invalid operand for instruction"); + return MatchOperand_ParseFail; + } + + RegNum = Reg.Num; + StartLoc = Reg.StartLoc; + EndLoc = Reg.EndLoc; } - if (!PrefixMatch) { - Error(Reg.StartLoc, "invalid operand for instruction"); - return MatchOperand_ParseFail; + // Also allow specifying just a plain register number as integer. + else if (Parser.getTok().is(AsmToken::Integer)) { + const MCExpr *Register; + StartLoc = Parser.getTok().getLoc(); + if (Parser.parseExpression(Register)) + return MatchOperand_ParseFail; + + auto *CE = dyn_cast(Register); + if (!CE) + return MatchOperand_ParseFail; + + int64_t MaxRegNum; + switch (Kind) { + case VR32Reg: + case VR64Reg: + case VR128Reg: + MaxRegNum = 31; + break; + default: + MaxRegNum = 15; + break; + } + int64_t Value = CE->getValue(); + if (Value < 0 || Value > MaxRegNum) { + Error(StartLoc, "invalid register"); + return MatchOperand_ParseFail; + } + RegNum = (unsigned) Value; + + EndLoc = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); } + // Otherwise we didn't match a register operand. + else + return MatchOperand_NoMatch; // Determine the LLVM register number according to Kind. const unsigned *Regs; @@ -804,13 +845,13 @@ SystemZAsmParser::parseRegister(OperandVector &Operands, RegisterKind Kind) { case AR32Reg: Regs = SystemZMC::AR32Regs; break; case CR64Reg: Regs = SystemZMC::CR64Regs; break; } - if (Regs[Reg.Num] == 0) { - Error(Reg.StartLoc, "invalid register pair"); + if (Regs[RegNum] == 0) { + Error(StartLoc, "invalid register pair"); return MatchOperand_ParseFail; } - Operands.push_back(SystemZOperand::createReg(Kind, Regs[Reg.Num], - Reg.StartLoc, Reg.EndLoc)); + Operands.push_back(SystemZOperand::createReg(Kind, Regs[RegNum], + StartLoc, EndLoc)); return MatchOperand_Success; } diff --git a/llvm/test/MC/SystemZ/regs-bad.s b/llvm/test/MC/SystemZ/regs-bad.s index c4d16ef..db56af9 100644 --- a/llvm/test/MC/SystemZ/regs-bad.s +++ b/llvm/test/MC/SystemZ/regs-bad.s @@ -15,9 +15,9 @@ #CHECK: lr %r0,%a1 #CHECK: error: invalid operand for instruction #CHECK: lr %r0,%c1 -#CHECK: error: invalid operand for instruction -#CHECK: lr %r0,0 -#CHECK: error: invalid operand for instruction +#CHECK: error: invalid register +#CHECK: lr %r0,16 +#CHECK: error: unexpected token in argument list #CHECK: lr %r0,0(%r1) lr %f0,%r1 @@ -26,7 +26,7 @@ lr %r0,%f1 lr %r0,%a1 lr %r0,%c1 - lr %r0,0 + lr %r0,16 lr %r0,0(%r1) # Test GR64 operands @@ -43,9 +43,9 @@ #CHECK: lgr %r0,%a1 #CHECK: error: invalid operand for instruction #CHECK: lgr %r0,%c1 -#CHECK: error: invalid operand for instruction -#CHECK: lgr %r0,0 -#CHECK: error: invalid operand for instruction +#CHECK: error: invalid register +#CHECK: lgr %r0,16 +#CHECK: error: unexpected token in argument list #CHECK: lgr %r0,0(%r1) lgr %f0,%r1 @@ -54,7 +54,7 @@ lgr %r0,%f1 lgr %r0,%a1 lgr %r0,%c1 - lgr %r0,0 + lgr %r0,16 lgr %r0,0(%r1) # Test GR128 operands @@ -87,9 +87,9 @@ #CHECK: dlr %r0,%a1 #CHECK: error: invalid operand for instruction #CHECK: dlr %r0,%c1 -#CHECK: error: invalid operand for instruction -#CHECK: dlr %r0,0 -#CHECK: error: invalid operand for instruction +#CHECK: error: invalid register +#CHECK: dlr %r0,16 +#CHECK: error: unexpected token in argument list #CHECK: dlr %r0,0(%r1) dlr %r1,%r0 @@ -106,7 +106,7 @@ dlr %r0,%f1 dlr %r0,%a1 dlr %r0,%c1 - dlr %r0,0 + dlr %r0,16 dlr %r0,0(%r1) # Test FP32 operands @@ -123,9 +123,9 @@ #CHECK: ler %f0,%a1 #CHECK: error: invalid operand for instruction #CHECK: ler %f0,%c1 -#CHECK: error: invalid operand for instruction -#CHECK: ler %f0,0 -#CHECK: error: invalid operand for instruction +#CHECK: error: invalid register +#CHECK: ler %f0,16 +#CHECK: error: unexpected token in argument list #CHECK: ler %f0,0(%r1) ler %r0,%f1 @@ -134,7 +134,7 @@ ler %f0,%r1 ler %f0,%a1 ler %f0,%c1 - ler %f0,0 + ler %f0,16 ler %f0,0(%r1) # Test FP64 operands @@ -151,9 +151,9 @@ #CHECK: ldr %f0,%a1 #CHECK: error: invalid operand for instruction #CHECK: ldr %f0,%c1 -#CHECK: error: invalid operand for instruction -#CHECK: ldr %f0,0 -#CHECK: error: invalid operand for instruction +#CHECK: error: invalid register +#CHECK: ldr %f0,16 +#CHECK: error: unexpected token in argument list #CHECK: ldr %f0,0(%r1) ldr %r0,%f1 @@ -162,7 +162,7 @@ ldr %f0,%r1 ldr %f0,%a1 ldr %f0,%c1 - ldr %f0,0 + ldr %f0,16 ldr %f0,0(%r1) # Test FP128 operands @@ -195,9 +195,9 @@ #CHECK: lxr %f0,%a1 #CHECK: error: invalid operand for instruction #CHECK: lxr %f0,%c1 -#CHECK: error: invalid operand for instruction -#CHECK: lxr %f0,0 -#CHECK: error: invalid operand for instruction +#CHECK: error: invalid register +#CHECK: lxr %f0,16 +#CHECK: error: unexpected token in argument list #CHECK: lxr %f0,0(%r1) lxr %f2,%f0 @@ -214,7 +214,7 @@ lxr %f0,%r1 lxr %f0,%a1 lxr %f0,%c1 - lxr %f0,0 + lxr %f0,16 lxr %f0,0(%r1) # Test access register operands @@ -225,15 +225,15 @@ #CHECK: ear %r0,%f0 #CHECK: error: invalid operand for instruction #CHECK: ear %r0,%c0 -#CHECK: error: invalid operand for instruction -#CHECK: ear %r0,0 -#CHECK: error: invalid operand for instruction +#CHECK: error: invalid register +#CHECK: ear %r0,16 +#CHECK: error: unexpected token in argument list #CHECK: ear %r0,0(%r1) ear %r0,%r0 ear %r0,%f0 ear %r0,%c0 - ear %r0,0 + ear %r0,16 ear %r0,0(%r1) # Test control register operands @@ -242,13 +242,13 @@ #CHECK: lctl %c0,%r0,0 #CHECK: lctl %c0,%f0,0 #CHECK: lctl %c0,%a0,0 -#CHECK: lctl %c0,0,0 +#CHECK: lctl %c0,16,0 #CHECK: lctl %c0,0(%r1),0 lctl %c0,%r0,0 lctl %c0,%f0,0 lctl %c0,%a0,0 - lctl %c0,0,0 + lctl %c0,16,0 lctl %c0,0(%r1),0 .cfi_startproc diff --git a/llvm/test/MC/SystemZ/regs-good.s b/llvm/test/MC/SystemZ/regs-good.s index c203011..c6157b5 100644 --- a/llvm/test/MC/SystemZ/regs-good.s +++ b/llvm/test/MC/SystemZ/regs-good.s @@ -8,6 +8,7 @@ #CHECK: lr %r10, %r11 # encoding: [0x18,0xab] #CHECK: lr %r12, %r13 # encoding: [0x18,0xcd] #CHECK: lr %r14, %r15 # encoding: [0x18,0xef] +#CHECK: lr %r0, %r15 # encoding: [0x18,0x0f] lr %r0,%r1 lr %r2,%r3 @@ -17,6 +18,7 @@ lr %r10,%r11 lr %r12,%r13 lr %r14,%r15 + lr 0,15 #CHECK: lgr %r0, %r1 # encoding: [0xb9,0x04,0x00,0x01] #CHECK: lgr %r2, %r3 # encoding: [0xb9,0x04,0x00,0x23] @@ -26,6 +28,7 @@ #CHECK: lgr %r10, %r11 # encoding: [0xb9,0x04,0x00,0xab] #CHECK: lgr %r12, %r13 # encoding: [0xb9,0x04,0x00,0xcd] #CHECK: lgr %r14, %r15 # encoding: [0xb9,0x04,0x00,0xef] +#CHECK: lgr %r0, %r15 # encoding: [0xb9,0x04,0x00,0x0f] lgr %r0,%r1 lgr %r2,%r3 @@ -35,6 +38,7 @@ lgr %r10,%r11 lgr %r12,%r13 lgr %r14,%r15 + lgr 0,15 #CHECK: dlr %r0, %r0 # encoding: [0xb9,0x97,0x00,0x00] #CHECK: dlr %r2, %r0 # encoding: [0xb9,0x97,0x00,0x20] @@ -44,6 +48,7 @@ #CHECK: dlr %r10, %r0 # encoding: [0xb9,0x97,0x00,0xa0] #CHECK: dlr %r12, %r0 # encoding: [0xb9,0x97,0x00,0xc0] #CHECK: dlr %r14, %r0 # encoding: [0xb9,0x97,0x00,0xe0] +#CHECK: dlr %r14, %r0 # encoding: [0xb9,0x97,0x00,0xe0] dlr %r0,%r0 dlr %r2,%r0 @@ -53,6 +58,7 @@ dlr %r10,%r0 dlr %r12,%r0 dlr %r14,%r0 + dlr 14,0 #CHECK: ler %f0, %f1 # encoding: [0x38,0x01] #CHECK: ler %f2, %f3 # encoding: [0x38,0x23] @@ -62,6 +68,7 @@ #CHECK: ler %f10, %f11 # encoding: [0x38,0xab] #CHECK: ler %f12, %f13 # encoding: [0x38,0xcd] #CHECK: ler %f14, %f15 # encoding: [0x38,0xef] +#CHECK: ler %f0, %f15 # encoding: [0x38,0x0f] ler %f0,%f1 ler %f2,%f3 @@ -71,6 +78,7 @@ ler %f10,%f11 ler %f12,%f13 ler %f14,%f15 + ler 0,15 #CHECK: ldr %f0, %f1 # encoding: [0x28,0x01] #CHECK: ldr %f2, %f3 # encoding: [0x28,0x23] @@ -80,6 +88,7 @@ #CHECK: ldr %f10, %f11 # encoding: [0x28,0xab] #CHECK: ldr %f12, %f13 # encoding: [0x28,0xcd] #CHECK: ldr %f14, %f15 # encoding: [0x28,0xef] +#CHECK: ldr %f0, %f15 # encoding: [0x28,0x0f] ldr %f0,%f1 ldr %f2,%f3 @@ -89,16 +98,19 @@ ldr %f10,%f11 ldr %f12,%f13 ldr %f14,%f15 + ldr 0,15 #CHECK: lxr %f0, %f1 # encoding: [0xb3,0x65,0x00,0x01] #CHECK: lxr %f4, %f5 # encoding: [0xb3,0x65,0x00,0x45] #CHECK: lxr %f8, %f9 # encoding: [0xb3,0x65,0x00,0x89] #CHECK: lxr %f12, %f13 # encoding: [0xb3,0x65,0x00,0xcd] +#CHECK: lxr %f0, %f13 # encoding: [0xb3,0x65,0x00,0x0d] lxr %f0,%f1 lxr %f4,%f5 lxr %f8,%f9 lxr %f12,%f13 + lxr 0,13 #CHECK: cpya %a0, %a1 # encoding: [0xb2,0x4d,0x00,0x01] #CHECK: cpya %a2, %a3 # encoding: [0xb2,0x4d,0x00,0x23] @@ -108,6 +120,7 @@ #CHECK: cpya %a10, %a11 # encoding: [0xb2,0x4d,0x00,0xab] #CHECK: cpya %a12, %a13 # encoding: [0xb2,0x4d,0x00,0xcd] #CHECK: cpya %a14, %a15 # encoding: [0xb2,0x4d,0x00,0xef] +#CHECK: cpya %a0, %a15 # encoding: [0xb2,0x4d,0x00,0x0f] cpya %a0,%a1 cpya %a2,%a3 @@ -117,6 +130,7 @@ cpya %a10,%a11 cpya %a12,%a13 cpya %a14,%a15 + cpya 0,15 #CHECK: lctl %c0, %c1, 0 # encoding: [0xb7,0x01,0x00,0x00] #CHECK: lctl %c2, %c3, 0 # encoding: [0xb7,0x23,0x00,0x00] @@ -126,6 +140,7 @@ #CHECK: lctl %c10, %c11, 0 # encoding: [0xb7,0xab,0x00,0x00] #CHECK: lctl %c12, %c13, 0 # encoding: [0xb7,0xcd,0x00,0x00] #CHECK: lctl %c14, %c15, 0 # encoding: [0xb7,0xef,0x00,0x00] +#CHECK: lctl %c0, %c15, 0 # encoding: [0xb7,0x0f,0x00,0x00] lctl %c0,%c1,0 lctl %c2,%c3,0 @@ -135,6 +150,7 @@ lctl %c10,%c11,0 lctl %c12,%c13,0 lctl %c14,%c15,0 + lctl 0,15,0 #CHECK: .cfi_offset %r0, 0 -- 2.7.4