[ms-inline asm] Add support for parsing the '.' operator. Given,
authorChad Rosier <mcrosier@apple.com>
Wed, 24 Oct 2012 22:21:50 +0000 (22:21 +0000)
committerChad Rosier <mcrosier@apple.com>
Wed, 24 Oct 2012 22:21:50 +0000 (22:21 +0000)
[register].field

The operator returns the value at the location pointed to by register plus the
offset of field within its structure or union.  This patch only handles
immediate fields (i.e., [eax].4).  The original displacement has to be a
MCConstantExpr as well.
Part of rdar://12470415 and rdar://12470514

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@166632 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/X86/AsmParser/X86AsmParser.cpp

index c752d5962eab0752536ef00c7bfb2684cbb35be0..708951126f542d07be880453b9157d680e093672 100644 (file)
@@ -60,6 +60,8 @@ private:
   X86Operand *ParseIntelBracExpression(unsigned SegReg, unsigned Size);
   X86Operand *ParseMemOperand(unsigned SegReg, SMLoc StartLoc);
 
+  const MCExpr *ParseIntelDotOperator(const MCExpr *Disp);
+
   bool ParseDirectiveWord(unsigned Size, SMLoc L);
   bool ParseDirectiveCode(StringRef IDVal, SMLoc L);
 
@@ -742,6 +744,11 @@ X86Operand *X86AsmParser::ParseIntelBracExpression(unsigned SegReg,
   Parser.Lex();
   End = Tok.getLoc();
 
+  if (Tok.getString().startswith("."))
+    Disp = ParseIntelDotOperator(Disp);
+
+  End = Tok.getLoc();
+
   // handle [-42]
   if (!BaseReg && !IndexReg)
     return X86Operand::CreateMem(Disp, Start, End, Size);
@@ -801,6 +808,33 @@ X86Operand *X86AsmParser::ParseIntelMemOperand(unsigned SegReg, SMLoc Start) {
                                  /*Scale*/1, Start, End, Size, NeedSizeDir);
 }
 
+/// Parse the '.' operator.
+const MCExpr *X86AsmParser::ParseIntelDotOperator(const MCExpr *Disp) {
+  AsmToken Tok = *&Parser.getTok();
+
+  // Drop the '.'.
+  StringRef DotDispStr = Tok.getString().drop_front(1);
+
+  Lex(); // Eat .field.
+
+  // .Imm gets lexed as a real.
+  if (Tok.is(AsmToken::Real)) {
+    APInt DotDisp;
+    DotDispStr.getAsInteger(10, DotDisp);
+    uint64_t DotDispVal = DotDisp.getZExtValue();
+
+    // Special case zero dot displacement.
+    if (!DotDispVal) return Disp;
+
+    // FIXME: Handle non-constant expressions.
+    if (const MCConstantExpr *OrigDisp = dyn_cast<MCConstantExpr>(Disp)) {
+      uint64_t OrigDispVal = OrigDisp->getValue();
+      return MCConstantExpr::Create(OrigDispVal + DotDispVal, getContext());
+    }
+  }
+  return Disp;
+}
+
 /// Parse the 'offset' operator.  This operator is used to specify the
 /// location rather then the content of a variable.
 X86Operand *X86AsmParser::ParseIntelOffsetOfOperator(SMLoc Start) {