[llvm] ca02fab - [AsmParser][SystemZ][z/OS] Implement HLASM location counter syntax ("*") for Z PC-relative instructions.

Anirudh Prasad via llvm-commits llvm-commits at lists.llvm.org
Mon May 3 11:58:30 PDT 2021


Author: Anirudh Prasad
Date: 2021-05-03T14:58:24-04:00
New Revision: ca02fab7e7b677f77e2c6e3dec172a3bb0a0b1c0

URL: https://github.com/llvm/llvm-project/commit/ca02fab7e7b677f77e2c6e3dec172a3bb0a0b1c0
DIFF: https://github.com/llvm/llvm-project/commit/ca02fab7e7b677f77e2c6e3dec172a3bb0a0b1c0.diff

LOG: [AsmParser][SystemZ][z/OS] Implement HLASM location counter syntax ("*") for Z PC-relative instructions.

- This patch attempts to implement the location counter syntax (*) for the HLASM variant for PC-relative instructions.
- In the HLASM variant, for purely constant relocatable values, we expect a * token preceding it, with special support for " *" which is parsed as "<pc-rel-insn 0>"
- For combinations of absolute values and relocatable values, we don't expect the "*" preceding the token.

When you have a " * "  what’s accepted is:

```
*<space>.*{.*} -> <pc-rel-insn> 0
*[+|-][constant-value] -> <pc-rel-insn> [+|-]constant-value
```

When you don’t have a " * " what’s accepted is:

```
brasl  1,func           is allowed (MCSymbolRef type)
brasl  1,func+4         is allowed (MCBinary type)
brasl  1,4+func         is allowed (MCBinary type)
brasl  1,-4+func        is allowed (MCBinary type)
brasl  1,func-4         is allowed (MCBinary type)
brasl  1,*func          is not allowed (* cannot be used for non-MCConstantExprs)
brasl  1,*+func         is not allowed (* cannot be used for non-MCConstantExprs)
brasl  1,*+func+4       is not allowed (* cannot be used for non-MCConstantExprs)
brasl  1,*+4+func       is not allowed (* cannot be used for non-MCConstantExprs)
brasl  1,*-4+8+func     is not allowed (* cannot be used for non-MCConstantExprs)
```

Reviewed By: Kai

Differential Revision: https://reviews.llvm.org/D100987

Added: 
    

Modified: 
    llvm/include/llvm/MC/MCAsmInfo.h
    llvm/lib/MC/MCParser/AsmParser.cpp
    llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp
    llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmInfo.cpp
    llvm/test/MC/AsmParser/directive_rept-diagnostics.s
    llvm/unittests/MC/SystemZ/SystemZAsmLexerTest.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/MC/MCAsmInfo.h b/llvm/include/llvm/MC/MCAsmInfo.h
index a0e7ba6e2a5aa..8de2f60d48984 100644
--- a/llvm/include/llvm/MC/MCAsmInfo.h
+++ b/llvm/include/llvm/MC/MCAsmInfo.h
@@ -122,6 +122,10 @@ class MCAsmInfo {
   /// to the current PC. Defaults to true.
   bool DotIsPC = true;
 
+  /// Whether the '*' token refers to the current PC. This is used for the
+  /// HLASM dialect.
+  bool StarIsPC = false;
+
   /// This string, if specified, is used to separate instructions from each
   /// other when on the same line.  Defaults to ';'
   const char *SeparatorString;
@@ -598,6 +602,7 @@ class MCAsmInfo {
   unsigned getMinInstAlignment() const { return MinInstAlignment; }
   bool getDollarIsPC() const { return DollarIsPC; }
   bool getDotIsPC() const { return DotIsPC; }
+  bool getStarIsPC() const { return StarIsPC; }
   const char *getSeparatorString() const { return SeparatorString; }
 
   /// This indicates the column (zero-based) at which asm comments should be

diff  --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp
index 5d037931bb0f5..5f807d8f7ef2c 100644
--- a/llvm/lib/MC/MCParser/AsmParser.cpp
+++ b/llvm/lib/MC/MCParser/AsmParser.cpp
@@ -1110,25 +1110,33 @@ bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc,
     Res = MCUnaryExpr::createLNot(Res, getContext(), FirstTokenLoc);
     return false;
   case AsmToken::Dollar:
+  case AsmToken::Star:
   case AsmToken::At:
   case AsmToken::String:
   case AsmToken::Identifier: {
     StringRef Identifier;
     if (parseIdentifier(Identifier)) {
-      // We may have failed but $ may be a valid token.
-      if (getTok().is(AsmToken::Dollar)) {
-        if (Lexer.getMAI().getDollarIsPC()) {
-          Lex();
-          // This is a '$' reference, which references the current PC.  Emit a
-          // temporary label to the streamer and refer to it.
-          MCSymbol *Sym = Ctx.createTempSymbol();
-          Out.emitLabel(Sym);
-          Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None,
-                                        getContext());
-          EndLoc = FirstTokenLoc;
-          return false;
-        }
-        return Error(FirstTokenLoc, "invalid token in expression");
+      // We may have failed but '$'|'*' may be a valid token in context of
+      // the current PC.
+      if (getTok().is(AsmToken::Dollar) || getTok().is(AsmToken::Star)) {
+        bool ShouldGenerateTempSymbol = false;
+        if ((getTok().is(AsmToken::Dollar) && MAI.getDollarIsPC()) ||
+            (getTok().is(AsmToken::Star) && MAI.getStarIsPC()))
+          ShouldGenerateTempSymbol = true;
+
+        if (!ShouldGenerateTempSymbol)
+          return Error(FirstTokenLoc, "invalid token in expression");
+
+        // Eat the '$'|'*' token.
+        Lex();
+        // This is either a '$'|'*' reference, which references the current PC.
+        // Emit a temporary label to the streamer and refer to it.
+        MCSymbol *Sym = Ctx.createTempSymbol();
+        Out.emitLabel(Sym);
+        Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None,
+                                      getContext());
+        EndLoc = FirstTokenLoc;
+        return false;
       }
     }
     // Parse symbol variant

diff  --git a/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp b/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp
index 42980d6174972..435c68165c385 100644
--- a/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp
+++ b/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp
@@ -1542,6 +1542,10 @@ SystemZAsmParser::parsePCRel(OperandVector &Operands, int64_t MinVal,
   // For consistency with the GNU assembler, treat immediates as offsets
   // from ".".
   if (auto *CE = dyn_cast<MCConstantExpr>(Expr)) {
+    if (isParsingHLASM()) {
+      Error(StartLoc, "Expected PC-relative expression");
+      return MatchOperand_ParseFail;
+    }
     if (isOutOfRangeConstant(CE)) {
       Error(StartLoc, "offset out of range");
       return MatchOperand_ParseFail;

diff  --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmInfo.cpp b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmInfo.cpp
index 6422ca93b6d77..e3d71f21f70c9 100644
--- a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmInfo.cpp
+++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmInfo.cpp
@@ -28,6 +28,7 @@ SystemZMCAsmInfo::SystemZMCAsmInfo(const Triple &TT) {
   AllowDollarAtStartOfIdentifier = (AssemblerDialect == AD_HLASM);
   AllowHashAtStartOfIdentifier = (AssemblerDialect == AD_HLASM);
   DotIsPC = (AssemblerDialect == AD_ATT);
+  StarIsPC = (AssemblerDialect == AD_HLASM);
 
   ZeroDirective = "\t.space\t";
   Data64bitsDirective = "\t.quad\t";

diff  --git a/llvm/test/MC/AsmParser/directive_rept-diagnostics.s b/llvm/test/MC/AsmParser/directive_rept-diagnostics.s
index 40c355514a054..3d12907656445 100644
--- a/llvm/test/MC/AsmParser/directive_rept-diagnostics.s
+++ b/llvm/test/MC/AsmParser/directive_rept-diagnostics.s
@@ -8,7 +8,7 @@
 invalid_expression:
 	.rept *
 
-# CHECK: error: unknown token in expression
+# CHECK: error: invalid token in expression
 # CHECK: 	.rept *
 # CHECK:              ^
 

diff  --git a/llvm/unittests/MC/SystemZ/SystemZAsmLexerTest.cpp b/llvm/unittests/MC/SystemZ/SystemZAsmLexerTest.cpp
index 6c868ce861674..353084a7a28b3 100644
--- a/llvm/unittests/MC/SystemZ/SystemZAsmLexerTest.cpp
+++ b/llvm/unittests/MC/SystemZ/SystemZAsmLexerTest.cpp
@@ -685,4 +685,19 @@ TEST_F(SystemZAsmLexerTest, CheckRejectDotAsCurrentPC) {
   EXPECT_EQ(ParsePrimaryExpr, true);
   EXPECT_EQ(Parser->hasPendingError(), true);
 }
+
+TEST_F(SystemZAsmLexerTest, CheckRejectStarAsCurrentPC) {
+  StringRef AsmStr = "*-4";
+
+  // Setup.
+  setupCallToAsmParser(AsmStr);
+
+  // Lex initially to get the string.
+  Parser->getLexer().Lex();
+
+  const MCExpr *Expr;
+  bool ParsePrimaryExpr = Parser->parseExpression(Expr);
+  EXPECT_EQ(ParsePrimaryExpr, true);
+  EXPECT_EQ(Parser->hasPendingError(), true);
+}
 } // end anonymous namespace


        


More information about the llvm-commits mailing list