[Sparc] Add support for parsing memory operands in sparc AsmParser.
authorVenkatraman Govindaraju <venkatra@cs.wisc.edu>
Tue, 7 Jan 2014 01:49:11 +0000 (01:49 +0000)
committerVenkatraman Govindaraju <venkatra@cs.wisc.edu>
Tue, 7 Jan 2014 01:49:11 +0000 (01:49 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@198658 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
lib/Target/Sparc/SparcInstrInfo.td
test/MC/Sparc/sparc-ctrl-instructions.s [new file with mode: 0644]
test/MC/Sparc/sparc-mem-instructions.s [new file with mode: 0644]

index d34678d401fe475fc175ecd6cced4ddca7511e07..13f62666fceca803ad76dfc22d627ef0b55476c9 100644 (file)
@@ -28,6 +28,7 @@ namespace llvm {
 }
 
 namespace {
+class SparcOperand;
 class SparcAsmParser : public MCTargetAsmParser {
 
   MCSubtargetInfo &STI;
@@ -55,18 +56,15 @@ class SparcAsmParser : public MCTargetAsmParser {
 
   // Custom parse functions for Sparc specific operands.
   OperandMatchResultTy
-  parseMEMrrOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
-  OperandMatchResultTy
-  parseMEMriOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
-
-  OperandMatchResultTy
-  parseMEMOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
-                  int ImmOffsetOrReg);
+  parseMEMOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
 
   OperandMatchResultTy
   parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
                StringRef Name);
 
+  OperandMatchResultTy
+  parseSparcAsmOperand(SparcOperand *&Operand);
+
   // returns true if Tok is matched to a register and returns register in RegNo.
   bool matchRegisterName(const AsmToken &Tok, unsigned &RegNo, bool isDFP,
                          bool isQFP);
@@ -298,7 +296,35 @@ public:
     return Op;
   }
 
+  static SparcOperand *MorphToMEMrr(unsigned Base, SparcOperand *Op) {
+    unsigned offsetReg = Op->getReg();
+    Op->Kind = k_MemoryReg;
+    Op->Mem.Base = Base;
+    Op->Mem.OffsetReg = offsetReg;
+    Op->Mem.Off = 0;
+    return Op;
+  }
 
+  static SparcOperand *CreateMEMri(unsigned Base,
+                                 const MCExpr *Off,
+                                 SMLoc S, SMLoc E) {
+    SparcOperand *Op = new SparcOperand(k_MemoryImm);
+    Op->Mem.Base = Base;
+    Op->Mem.OffsetReg = 0;
+    Op->Mem.Off = Off;
+    Op->StartLoc = S;
+    Op->EndLoc = E;
+    return Op;
+  }
+
+  static SparcOperand *MorphToMEMri(unsigned Base, SparcOperand *Op) {
+    const MCExpr *Imm  = Op->getImm();
+    Op->Kind = k_MemoryImm;
+    Op->Mem.Base = Base;
+    Op->Mem.OffsetReg = 0;
+    Op->Mem.Off = Imm;
+    return Op;
+  }
 };
 
 } // end namespace
@@ -412,43 +438,99 @@ ParseDirective(AsmToken DirectiveID)
 }
 
 SparcAsmParser::OperandMatchResultTy SparcAsmParser::
-parseMEMOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
-                int ImmOffsetOrReg)
+parseMEMOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands)
 {
-  // FIXME: Implement memory operand parsing here.
-  return MatchOperand_NoMatch;
-}
 
-SparcAsmParser::OperandMatchResultTy SparcAsmParser::
-parseMEMrrOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands)
-{
-  return parseMEMOperand(Operands, 2);
-}
+  SMLoc S, E;
+  unsigned BaseReg = 0;
 
-SparcAsmParser::OperandMatchResultTy SparcAsmParser::
-parseMEMriOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands)
-{
-  return parseMEMOperand(Operands, 1);
+  if (ParseRegister(BaseReg, S, E)) {
+    return MatchOperand_NoMatch;
+  }
+
+  switch (getLexer().getKind()) {
+  default: return MatchOperand_NoMatch;
+
+  case AsmToken::RBrac:
+  case AsmToken::EndOfStatement:
+    Operands.push_back(SparcOperand::CreateMEMri(BaseReg, 0, S, E));
+    return MatchOperand_Success;
+
+  case AsmToken:: Plus:
+    Parser.Lex(); // Eat the '+'
+    break;
+  case AsmToken::Minus:
+    break;
+  }
+
+  SparcOperand *Offset = 0;
+  OperandMatchResultTy ResTy = parseSparcAsmOperand(Offset);
+  if (ResTy != MatchOperand_Success || !Offset)
+    return MatchOperand_NoMatch;
+
+  Offset = (Offset->isImm()
+            ? SparcOperand::MorphToMEMri(BaseReg, Offset)
+            : SparcOperand::MorphToMEMrr(BaseReg, Offset));
+
+  Operands.push_back(Offset);
+  return MatchOperand_Success;
 }
 
 SparcAsmParser::OperandMatchResultTy SparcAsmParser::
 parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
              StringRef Mnemonic)
 {
+
   OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
-  if (ResTy == MatchOperand_Success)
-    return ResTy;
+
   // If there wasn't a custom match, try the generic matcher below. Otherwise,
   // there was a match, but an error occurred, in which case, just return that
   // the operand parsing failed.
-  if (ResTy == MatchOperand_ParseFail)
+  if (ResTy == MatchOperand_Success || ResTy == MatchOperand_ParseFail)
     return ResTy;
 
+  if (getLexer().is(AsmToken::LBrac)) {
+    // Memory operand
+    Operands.push_back(SparcOperand::CreateToken("[",
+                                                 Parser.getTok().getLoc()));
+    Parser.Lex(); // Eat the [
+
+    ResTy = parseMEMOperand(Operands);
+    if (ResTy != MatchOperand_Success)
+      return ResTy;
+
+    if (!getLexer().is(AsmToken::RBrac))
+      return MatchOperand_ParseFail;
+
+    Operands.push_back(SparcOperand::CreateToken("]",
+                                                 Parser.getTok().getLoc()));
+    Parser.Lex(); // Eat the ]
+    return MatchOperand_Success;
+  }
+
+  SparcOperand *Op = 0;
+  ResTy = parseSparcAsmOperand(Op);
+  if (ResTy != MatchOperand_Success || !Op)
+    return MatchOperand_ParseFail;
+
+  // Push the parsed operand into the list of operands
+  Operands.push_back(Op);
+
+  return MatchOperand_Success;
+}
+
+SparcAsmParser::OperandMatchResultTy
+SparcAsmParser::parseSparcAsmOperand(SparcOperand *&Op)
+{
+
   SMLoc S = Parser.getTok().getLoc();
   SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
   const MCExpr *EVal;
-  SparcOperand *Op;
+
+  Op = 0;
   switch (getLexer().getKind()) {
+  default:  break;
+
   case AsmToken::Percent:
     Parser.Lex(); // Eat the '%'.
     unsigned RegNo;
@@ -458,40 +540,30 @@ parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
       break;
     }
     // FIXME: Handle modifiers like %hi, %lo etc.,
-    return MatchOperand_ParseFail;
+    break;
 
   case AsmToken::Minus:
   case AsmToken::Integer:
-    if (getParser().parseExpression(EVal))
-      return MatchOperand_ParseFail;
-
-    Op = SparcOperand::CreateImm(EVal, S, E);
+    if (!getParser().parseExpression(EVal))
+      Op = SparcOperand::CreateImm(EVal, S, E);
     break;
 
   case AsmToken::Identifier: {
     StringRef Identifier;
-    if (getParser().parseIdentifier(Identifier))
-      return MatchOperand_ParseFail;
-    SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
-    MCSymbol *Sym = getContext().GetOrCreateSymbol(Identifier);
+    if (!getParser().parseIdentifier(Identifier)) {
+      SMLoc E = SMLoc::getFromPointer(Parser.getTok().
+                                      getLoc().getPointer() - 1);
+      MCSymbol *Sym = getContext().GetOrCreateSymbol(Identifier);
 
-    // Otherwise create a symbol reference.
-    const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
-                                                getContext());
+      const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
+                                                  getContext());
 
-    Op = SparcOperand::CreateImm(Res, S, E);
+      Op = SparcOperand::CreateImm(Res, S, E);
+    }
     break;
   }
-
-  case AsmToken::LBrac:  // handle [
-    return parseMEMOperand(Operands, 0);
-
-  default:
-    return MatchOperand_ParseFail;
   }
-  // Push the parsed operand into the list of operands
-  Operands.push_back(Op);
-  return MatchOperand_Success;
+  return (Op) ? MatchOperand_Success : MatchOperand_ParseFail;
 }
 
 bool SparcAsmParser::matchRegisterName(const AsmToken &Tok,
index c1ebbca9232717edb20f6ef1188c6a0728ec4494..7808a1aea4ccbc66ef630d475603851e7870a6b5 100644 (file)
@@ -78,12 +78,12 @@ def ADDRri : ComplexPattern<iPTR, 2, "SelectADDRri", [frameindex], []>;
 // Address operands
 def SparcMEMrrAsmOperand : AsmOperandClass {
   let Name = "MEMrr";
-  let ParserMethod = "parseMEMrrOperand";
+  let ParserMethod = "parseMEMOperand";
 }
 
 def SparcMEMriAsmOperand : AsmOperandClass {
   let Name = "MEMri";
-  let ParserMethod = "parseMEMriOperand";
+  let ParserMethod = "parseMEMOperand";
 }
 
 def MEMrr : Operand<iPTR> {
diff --git a/test/MC/Sparc/sparc-ctrl-instructions.s b/test/MC/Sparc/sparc-ctrl-instructions.s
new file mode 100644 (file)
index 0000000..5a2c597
--- /dev/null
@@ -0,0 +1,23 @@
+! RUN: llvm-mc %s -arch=sparc   -show-encoding | FileCheck %s
+! RUN: llvm-mc %s -arch=sparcv9 -show-encoding | FileCheck %s
+
+        ! CHECK: call foo
+        call foo
+
+        ! CHECK: call %g1+%i2
+        call %g1 + %i2
+
+        ! CHECK: call %o1+8
+        call %o1 + 8
+
+        ! CHECK: call %g1
+        call %g1
+
+        ! CHECK: jmp %g1+%i2
+        jmp %g1 + %i2
+
+        ! CHECK: jmp %o1+8
+        jmp %o1 + 8
+
+        ! CHECK: jmp %g1
+        jmp %g1
diff --git a/test/MC/Sparc/sparc-mem-instructions.s b/test/MC/Sparc/sparc-mem-instructions.s
new file mode 100644 (file)
index 0000000..e8eb593
--- /dev/null
@@ -0,0 +1,58 @@
+! RUN: llvm-mc %s -arch=sparc   -show-encoding | FileCheck %s
+! RUN: llvm-mc %s -arch=sparcv9 -show-encoding | FileCheck %s
+
+        ! CHECK: ldsb [%i0+%l6], %o2  ! encoding: [0xd4,0x4e,0x00,0x16]
+        ldsb [%i0 + %l6], %o2
+        ! CHECK: ldsb [%i0+32], %o2   ! encoding: [0xd4,0x4e,0x20,0x20]
+        ldsb [%i0 + 32], %o2
+        ! CHECK: ldsb [%g1], %o4      ! encoding: [0xd8,0x48,0x60,0x00]
+        ldsb [%g1], %o4
+
+        ! CHECK: ldsh [%i0+%l6], %o2  ! encoding: [0xd4,0x56,0x00,0x16]
+        ldsh [%i0 + %l6], %o2
+        ! CHECK: ldsh [%i0+32], %o2   ! encoding: [0xd4,0x56,0x20,0x20]
+        ldsh [%i0 + 32], %o2
+        ! CHECK: ldsh [%g1], %o4      ! encoding: [0xd8,0x50,0x60,0x00]
+        ldsh [%g1], %o4
+
+        ! CHECK: ldub [%i0+%l6], %o2  ! encoding: [0xd4,0x0e,0x00,0x16]
+        ldub [%i0 + %l6], %o2
+        ! CHECK: ldub [%i0+32], %o2   ! encoding: [0xd4,0x0e,0x20,0x20]
+        ldub [%i0 + 32], %o2
+        ! CHECK: ldub [%g1], %o2      ! encoding: [0xd4,0x08,0x60,0x00]
+        ldub [%g1], %o2
+
+        ! CHECK: lduh [%i0+%l6], %o2  ! encoding: [0xd4,0x16,0x00,0x16]
+        lduh [%i0 + %l6], %o2
+        ! CHECK: lduh [%i0+32], %o2   ! encoding: [0xd4,0x16,0x20,0x20]
+        lduh [%i0 + 32], %o2
+        ! CHECK: lduh [%g1], %o2      ! encoding: [0xd4,0x10,0x60,0x00]
+        lduh [%g1], %o2
+
+        ! CHECK: ld [%i0+%l6], %o2    ! encoding: [0xd4,0x06,0x00,0x16]
+        ld [%i0 + %l6], %o2
+        ! CHECK: ld [%i0+32], %o2     ! encoding: [0xd4,0x06,0x20,0x20]
+        ld [%i0 + 32], %o2
+        ! CHECK: ld [%g1], %o2        ! encoding: [0xd4,0x00,0x60,0x00]
+        ld [%g1], %o2
+
+        ! CHECK: stb %o2, [%i0+%l6]   ! encoding: [0xd4,0x2e,0x00,0x16]
+        stb %o2, [%i0 + %l6]
+        ! CHECK: stb %o2, [%i0+32]    ! encoding: [0xd4,0x2e,0x20,0x20]
+        stb %o2, [%i0 + 32]
+        ! CHECK: stb %o2, [%g1]       ! encoding: [0xd4,0x28,0x60,0x00]
+        stb %o2, [%g1]
+
+        ! CHECK: sth %o2, [%i0+%l6]   ! encoding: [0xd4,0x36,0x00,0x16]
+        sth %o2, [%i0 + %l6]
+        ! CHECK: sth %o2, [%i0+32]    ! encoding: [0xd4,0x36,0x20,0x20]
+        sth %o2, [%i0 + 32]
+        ! CHECK: sth %o2, [%g1]       ! encoding: [0xd4,0x30,0x60,0x00]
+        sth %o2, [%g1]
+
+        ! CHECK: st %o2, [%i0+%l6]    ! encoding: [0xd4,0x26,0x00,0x16]
+        st %o2, [%i0 + %l6]
+        ! CHECK: st %o2, [%i0+32]     ! encoding: [0xd4,0x26,0x20,0x20]
+        st %o2, [%i0 + 32]
+        ! CHECK: st %o2, [%g1]        ! encoding: [0xd4,0x20,0x60,0x00]
+        st %o2, [%g1]