[llvm] fa1fecc - [VE] Support symbol with offset in assembly

Kazushi Marukawa via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 6 12:16:59 PDT 2020


Author: Kazushi (Jam) Marukawa
Date: 2020-07-07T04:16:51+09:00
New Revision: fa1fecc73d4d3884ae8eb887ac06c0f7f7492053

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

LOG: [VE] Support symbol with offset in assembly

Summary:
Change MCExpr to support Aurora VE's modifiers.  Change asmparser to use
existing MCExpr parser (parseExpression) to parse an expression contining
symbols with modifiers and offsets.  Also add several regression tests
of MC layer.

Reviewers: simoll, k-ishizaka

Reviewed By: simoll

Subscribers: hiraditya, llvm-commits

Tags: #llvm, #ve

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

Added: 
    llvm/test/MC/VE/sym-br.s

Modified: 
    llvm/include/llvm/MC/MCExpr.h
    llvm/lib/MC/MCExpr.cpp
    llvm/lib/Target/VE/AsmParser/VEAsmParser.cpp
    llvm/test/MC/VE/symbols.s

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/MC/MCExpr.h b/llvm/include/llvm/MC/MCExpr.h
index 776e116a6e16..803c0d443bee 100644
--- a/llvm/include/llvm/MC/MCExpr.h
+++ b/llvm/include/llvm/MC/MCExpr.h
@@ -327,6 +327,21 @@ class MCSymbolRefExpr : public MCExpr {
     VK_AMDGPU_ABS32_LO,      // symbol at abs32@lo
     VK_AMDGPU_ABS32_HI,      // symbol at abs32@hi
 
+    VK_VE_HI32,        // symbol at hi
+    VK_VE_LO32,        // symbol at lo
+    VK_VE_PC_HI32,     // symbol at pc_hi
+    VK_VE_PC_LO32,     // symbol at pc_lo
+    VK_VE_GOT_HI32,    // symbol at got_hi
+    VK_VE_GOT_LO32,    // symbol at got_lo
+    VK_VE_GOTOFF_HI32, // symbol at gotoff_hi
+    VK_VE_GOTOFF_LO32, // symbol at gotoff_lo
+    VK_VE_PLT_HI32,    // symbol at plt_hi
+    VK_VE_PLT_LO32,    // symbol at plt_lo
+    VK_VE_TLS_GD_HI32, // symbol at tls_gd_hi
+    VK_VE_TLS_GD_LO32, // symbol at tls_gd_lo
+    VK_VE_TPOFF_HI32,  // symbol at tpoff_hi
+    VK_VE_TPOFF_LO32,  // symbol at tpoff_lo
+
     VK_TPREL,
     VK_DTPREL
   };

diff  --git a/llvm/lib/MC/MCExpr.cpp b/llvm/lib/MC/MCExpr.cpp
index fdb83aeef5eb..ecf63b10f73f 100644
--- a/llvm/lib/MC/MCExpr.cpp
+++ b/llvm/lib/MC/MCExpr.cpp
@@ -342,6 +342,20 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) {
   case VK_AMDGPU_REL64: return "rel64";
   case VK_AMDGPU_ABS32_LO: return "abs32 at lo";
   case VK_AMDGPU_ABS32_HI: return "abs32 at hi";
+  case VK_VE_HI32: return "hi";
+  case VK_VE_LO32: return "lo";
+  case VK_VE_PC_HI32: return "pc_hi";
+  case VK_VE_PC_LO32: return "pc_lo";
+  case VK_VE_GOT_HI32: return "got_hi";
+  case VK_VE_GOT_LO32: return "got_lo";
+  case VK_VE_GOTOFF_HI32: return "gotoff_hi";
+  case VK_VE_GOTOFF_LO32: return "gotoff_lo";
+  case VK_VE_PLT_HI32: return "plt_hi";
+  case VK_VE_PLT_LO32: return "plt_lo";
+  case VK_VE_TLS_GD_HI32: return "tls_gd_hi";
+  case VK_VE_TLS_GD_LO32: return "tls_gd_lo";
+  case VK_VE_TPOFF_HI32: return "tpoff_hi";
+  case VK_VE_TPOFF_LO32: return "tpoff_lo";
   }
   llvm_unreachable("Invalid variant kind");
 }
@@ -463,6 +477,20 @@ MCSymbolRefExpr::getVariantKindForName(StringRef Name) {
     .Case("rel64", VK_AMDGPU_REL64)
     .Case("abs32 at lo", VK_AMDGPU_ABS32_LO)
     .Case("abs32 at hi", VK_AMDGPU_ABS32_HI)
+    .Case("hi", VK_VE_HI32)
+    .Case("lo", VK_VE_LO32)
+    .Case("pc_hi", VK_VE_PC_HI32)
+    .Case("pc_lo", VK_VE_PC_LO32)
+    .Case("got_hi", VK_VE_GOT_HI32)
+    .Case("got_lo", VK_VE_GOT_LO32)
+    .Case("gotoff_hi", VK_VE_GOTOFF_HI32)
+    .Case("gotoff_lo", VK_VE_GOTOFF_LO32)
+    .Case("plt_hi", VK_VE_PLT_HI32)
+    .Case("plt_lo", VK_VE_PLT_LO32)
+    .Case("tls_gd_hi", VK_VE_TLS_GD_HI32)
+    .Case("tls_gd_lo", VK_VE_TLS_GD_LO32)
+    .Case("tpoff_hi", VK_VE_TPOFF_HI32)
+    .Case("tpoff_lo", VK_VE_TPOFF_LO32)
     .Default(VK_Invalid);
 }
 

diff  --git a/llvm/lib/Target/VE/AsmParser/VEAsmParser.cpp b/llvm/lib/Target/VE/AsmParser/VEAsmParser.cpp
index 214adf4c3c5b..7a899b4b38e2 100644
--- a/llvm/lib/Target/VE/AsmParser/VEAsmParser.cpp
+++ b/llvm/lib/Target/VE/AsmParser/VEAsmParser.cpp
@@ -65,8 +65,6 @@ class VEAsmParser : public MCTargetAsmParser {
   unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
                                       unsigned Kind) override;
 
-  // Helper function to parse and generate identifier with relocation.
-  const MCExpr *parseIdentifier(StringRef Identifier);
   // Custom parse functions for VE specific operands.
   OperandMatchResultTy parseMEMOperand(OperandVector &Operands);
   OperandMatchResultTy parseMEMAsOperand(OperandVector &Operands);
@@ -75,6 +73,13 @@ class VEAsmParser : public MCTargetAsmParser {
   OperandMatchResultTy parseMImmOperand(OperandVector &Operands);
   OperandMatchResultTy parseOperand(OperandVector &Operands, StringRef Name);
   OperandMatchResultTy parseVEAsmOperand(std::unique_ptr<VEOperand> &Operand);
+
+  // Helper function to parse expression with a symbol.
+  const MCExpr *extractModifierFromExpr(const MCExpr *E,
+                                        VEMCExpr::VariantKind &Variant);
+  const MCExpr *fixupVariantKind(const MCExpr *E);
+  bool parseExpression(const MCExpr *&EVal);
+
   // Split the mnemonic stripping conditional code and quantifiers
   StringRef splitMnemonic(StringRef Name, SMLoc NameLoc,
                           OperandVector *Operands);
@@ -948,27 +953,163 @@ bool VEAsmParser::ParseDirective(AsmToken DirectiveID) {
   return true;
 }
 
-const MCExpr *VEAsmParser::parseIdentifier(StringRef Identifier) {
-  StringRef Modifier;
-  // Search @modifiers like "symbol at hi".
-  size_t at = Identifier.rfind('@');
-  if (at != 0 || at != StringRef::npos) {
-    std::pair<StringRef, StringRef> Pair = Identifier.rsplit("@");
-    if (!Pair.first.empty() && !Pair.second.empty()) {
-      Identifier = Pair.first;
-      Modifier = Pair.second;
+/// Extract \code @lo32/@hi32/etc \endcode modifier from expression.
+/// Recursively scan the expression and check for VK_VE_HI32/LO32/etc
+/// symbol variants.  If all symbols with modifier use the same
+/// variant, return the corresponding VEMCExpr::VariantKind,
+/// and a modified expression using the default symbol variant.
+/// Otherwise, return NULL.
+const MCExpr *
+VEAsmParser::extractModifierFromExpr(const MCExpr *E,
+                                     VEMCExpr::VariantKind &Variant) {
+  MCContext &Context = getParser().getContext();
+  Variant = VEMCExpr::VK_VE_None;
+
+  switch (E->getKind()) {
+  case MCExpr::Target:
+  case MCExpr::Constant:
+    return nullptr;
+
+  case MCExpr::SymbolRef: {
+    const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(E);
+
+    switch (SRE->getKind()) {
+    case MCSymbolRefExpr::VK_None:
+      // Use VK_VE_REFLONG to a symbol without modifiers.
+      Variant = VEMCExpr::VK_VE_REFLONG;
+      break;
+    case MCSymbolRefExpr::VK_VE_HI32:
+      Variant = VEMCExpr::VK_VE_HI32;
+      break;
+    case MCSymbolRefExpr::VK_VE_LO32:
+      Variant = VEMCExpr::VK_VE_LO32;
+      break;
+    case MCSymbolRefExpr::VK_VE_PC_HI32:
+      Variant = VEMCExpr::VK_VE_PC_HI32;
+      break;
+    case MCSymbolRefExpr::VK_VE_PC_LO32:
+      Variant = VEMCExpr::VK_VE_PC_LO32;
+      break;
+    case MCSymbolRefExpr::VK_VE_GOT_HI32:
+      Variant = VEMCExpr::VK_VE_GOT_HI32;
+      break;
+    case MCSymbolRefExpr::VK_VE_GOT_LO32:
+      Variant = VEMCExpr::VK_VE_GOT_LO32;
+      break;
+    case MCSymbolRefExpr::VK_VE_GOTOFF_HI32:
+      Variant = VEMCExpr::VK_VE_GOTOFF_HI32;
+      break;
+    case MCSymbolRefExpr::VK_VE_GOTOFF_LO32:
+      Variant = VEMCExpr::VK_VE_GOTOFF_LO32;
+      break;
+    case MCSymbolRefExpr::VK_VE_PLT_HI32:
+      Variant = VEMCExpr::VK_VE_PLT_HI32;
+      break;
+    case MCSymbolRefExpr::VK_VE_PLT_LO32:
+      Variant = VEMCExpr::VK_VE_PLT_LO32;
+      break;
+    case MCSymbolRefExpr::VK_VE_TLS_GD_HI32:
+      Variant = VEMCExpr::VK_VE_TLS_GD_HI32;
+      break;
+    case MCSymbolRefExpr::VK_VE_TLS_GD_LO32:
+      Variant = VEMCExpr::VK_VE_TLS_GD_LO32;
+      break;
+    case MCSymbolRefExpr::VK_VE_TPOFF_HI32:
+      Variant = VEMCExpr::VK_VE_TPOFF_HI32;
+      break;
+    case MCSymbolRefExpr::VK_VE_TPOFF_LO32:
+      Variant = VEMCExpr::VK_VE_TPOFF_LO32;
+      break;
+    default:
+      return nullptr;
     }
+
+    return MCSymbolRefExpr::create(&SRE->getSymbol(), Context);
   }
-  MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
-  const MCExpr *Res =
-      MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
-  VEMCExpr::VariantKind VK = VEMCExpr::parseVariantKind(Modifier);
-  if (VK == VEMCExpr::VK_VE_None) {
-    // Create identifier using default variant kind
-    VEMCExpr::VariantKind Kind = VEMCExpr::VK_VE_REFLONG;
-    return VEMCExpr::create(Kind, Res, getContext());
+
+  case MCExpr::Unary: {
+    const MCUnaryExpr *UE = cast<MCUnaryExpr>(E);
+    const MCExpr *Sub = extractModifierFromExpr(UE->getSubExpr(), Variant);
+    if (!Sub)
+      return nullptr;
+    return MCUnaryExpr::create(UE->getOpcode(), Sub, Context);
   }
-  return VEMCExpr::create(VK, Res, getContext());
+
+  case MCExpr::Binary: {
+    const MCBinaryExpr *BE = cast<MCBinaryExpr>(E);
+    VEMCExpr::VariantKind LHSVariant, RHSVariant;
+    const MCExpr *LHS = extractModifierFromExpr(BE->getLHS(), LHSVariant);
+    const MCExpr *RHS = extractModifierFromExpr(BE->getRHS(), RHSVariant);
+
+    if (!LHS && !RHS)
+      return nullptr;
+
+    if (!LHS)
+      LHS = BE->getLHS();
+    if (!RHS)
+      RHS = BE->getRHS();
+
+    if (LHSVariant == VEMCExpr::VK_VE_None)
+      Variant = RHSVariant;
+    else if (RHSVariant == VEMCExpr::VK_VE_None)
+      Variant = LHSVariant;
+    else if (LHSVariant == RHSVariant)
+      Variant = LHSVariant;
+    else
+      return nullptr;
+
+    return MCBinaryExpr::create(BE->getOpcode(), LHS, RHS, Context);
+  }
+  }
+
+  llvm_unreachable("Invalid expression kind!");
+}
+
+const MCExpr *VEAsmParser::fixupVariantKind(const MCExpr *E) {
+  MCContext &Context = getParser().getContext();
+
+  switch (E->getKind()) {
+  case MCExpr::Target:
+  case MCExpr::Constant:
+  case MCExpr::SymbolRef:
+    return E;
+
+  case MCExpr::Unary: {
+    const MCUnaryExpr *UE = cast<MCUnaryExpr>(E);
+    const MCExpr *Sub = fixupVariantKind(UE->getSubExpr());
+    if (Sub == UE->getSubExpr())
+      return E;
+    return MCUnaryExpr::create(UE->getOpcode(), Sub, Context);
+  }
+
+  case MCExpr::Binary: {
+    const MCBinaryExpr *BE = cast<MCBinaryExpr>(E);
+    const MCExpr *LHS = fixupVariantKind(BE->getLHS());
+    const MCExpr *RHS = fixupVariantKind(BE->getRHS());
+    if (LHS == BE->getLHS() && RHS == BE->getRHS())
+      return E;
+    return MCBinaryExpr::create(BE->getOpcode(), LHS, RHS, Context);
+  }
+  }
+
+  llvm_unreachable("Invalid expression kind!");
+}
+
+/// ParseExpression.  This 
diff ers from the default "parseExpression" in that
+/// it handles modifiers.
+bool VEAsmParser::parseExpression(const MCExpr *&EVal) {
+  // Handle \code symbol @lo32/@hi32/etc \endcode.
+  if (getParser().parseExpression(EVal))
+    return true;
+
+  // Convert MCSymbolRefExpr with VK_* to MCExpr with VK_*.
+  EVal = fixupVariantKind(EVal);
+  VEMCExpr::VariantKind Variant;
+  const MCExpr *E = extractModifierFromExpr(EVal, Variant);
+  if (E)
+    EVal = VEMCExpr::create(Variant, E, getParser().getContext());
+
+  return false;
 }
 
 OperandMatchResultTy VEAsmParser::parseMEMOperand(OperandVector &Operands) {
@@ -992,27 +1133,16 @@ OperandMatchResultTy VEAsmParser::parseMEMOperand(OperandVector &Operands) {
 
   case AsmToken::Minus:
   case AsmToken::Integer:
-  case AsmToken::Dot: {
+  case AsmToken::Dot:
+  case AsmToken::Identifier: {
     const MCExpr *EVal;
-    if (!getParser().parseExpression(EVal, E))
+    if (!parseExpression(EVal))
       Offset = VEOperand::CreateImm(EVal, S, E);
     else
       return MatchOperand_NoMatch;
     break;
   }
 
-  case AsmToken::Identifier: {
-    StringRef Identifier;
-    if (!getParser().parseIdentifier(Identifier)) {
-      E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
-      const MCExpr *EVal = parseIdentifier(Identifier);
-
-      E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
-      Offset = VEOperand::CreateImm(EVal, S, E);
-    }
-    break;
-  }
-
   case AsmToken::LParen:
     // empty disp (= 0)
     Offset =
@@ -1110,9 +1240,10 @@ OperandMatchResultTy VEAsmParser::parseMEMAsOperand(OperandVector &Operands) {
 
   case AsmToken::Minus:
   case AsmToken::Integer:
-  case AsmToken::Dot: {
+  case AsmToken::Dot:
+  case AsmToken::Identifier: {
     const MCExpr *EVal;
-    if (!getParser().parseExpression(EVal, E))
+    if (!parseExpression(EVal))
       Offset = VEOperand::CreateImm(EVal, S, E);
     else
       return MatchOperand_NoMatch;
@@ -1275,22 +1406,10 @@ VEAsmParser::parseVEAsmOperand(std::unique_ptr<VEOperand> &Op) {
   case AsmToken::Minus:
   case AsmToken::Integer:
   case AsmToken::Dot:
-    if (!getParser().parseExpression(EVal, E))
+  case AsmToken::Identifier:
+    if (!parseExpression(EVal))
       Op = VEOperand::CreateImm(EVal, S, E);
     break;
-
-  case AsmToken::Identifier: {
-    StringRef Identifier;
-    if (!getParser().parseIdentifier(Identifier)) {
-      E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
-      MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
-
-      const MCExpr *Res =
-          MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
-      Op = VEOperand::CreateImm(Res, S, E);
-    }
-    break;
-  }
   }
   return (Op) ? MatchOperand_Success : MatchOperand_ParseFail;
 }

diff  --git a/llvm/test/MC/VE/sym-br.s b/llvm/test/MC/VE/sym-br.s
new file mode 100644
index 000000000000..87800b518b06
--- /dev/null
+++ b/llvm/test/MC/VE/sym-br.s
@@ -0,0 +1,10 @@
+# RUN: llvm-mc -triple=ve %s -o - | FileCheck %s
+# RUN: llvm-mc -triple=ve -filetype=obj %s -o - | llvm-objdump -r - | FileCheck %s --check-prefix=CHECK-OBJ
+
+        b.l.t tgt(, %s1)
+        b.l.t tgt+24(, %s1)
+# CHECK: b.l.t tgt(, %s1)
+# CHECK-NEXT: b.l.t tgt+24(, %s1)
+
+# CHECK-OBJ: 0 R_VE_REFLONG tgt
+# CHECK-OBJ-NEXT: 8 R_VE_REFLONG tgt+0x18

diff  --git a/llvm/test/MC/VE/symbols.s b/llvm/test/MC/VE/symbols.s
index 55702f89258c..1f1d9a341af6 100644
--- a/llvm/test/MC/VE/symbols.s
+++ b/llvm/test/MC/VE/symbols.s
@@ -5,11 +5,19 @@
         lea %s1, var at lo
         and %s1, %s1, (32)0
         lea.sl %s1, var at hi(, %s1)
+        lea %s1, var+8 at lo
+        and %s1, %s1, (32)0
+        lea.sl %s1, var+8 at hi(, %s1)
 # CHECK: lea %s0, var
 # CHECK-NEXT: lea %s1, var at lo
 # CHECK-NEXT: and %s1, %s1, (32)0
 # CHECK-NEXT: lea.sl %s1, var at hi(, %s1)
+# CHECK-NEXT: lea %s1, var+8 at lo
+# CHECK-NEXT: and %s1, %s1, (32)0
+# CHECK-NEXT: lea.sl %s1, var+8 at hi(, %s1)
 
 # CHECK-OBJ: 0 R_VE_REFLONG var
 # CHECK-OBJ-NEXT: 8 R_VE_LO32 var
 # CHECK-OBJ-NEXT: 18 R_VE_HI32 var
+# CHECK-OBJ-NEXT: 20 R_VE_LO32 var+0x8
+# CHECK-OBJ-NEXT: 30 R_VE_HI32 var+0x8


        


More information about the llvm-commits mailing list