[llvm] r179393 - [ms-inline asm] Add support for operands that include both a symbol and an

Chad Rosier mcrosier at apple.com
Fri Apr 12 11:21:18 PDT 2013


Author: mcrosier
Date: Fri Apr 12 13:21:18 2013
New Revision: 179393

URL: http://llvm.org/viewvc/llvm-project?rev=179393&view=rev
Log:
[ms-inline asm] Add support for operands that include both a symbol and an
immediate displacement.  Specifically, add support for generating the proper IR.
We've been able to parse this for some time now.  Test case to be added on the
clang side.
Part of rdar://13453209

Modified:
    llvm/trunk/lib/Target/X86/AsmParser/X86AsmParser.cpp

Modified: llvm/trunk/lib/Target/X86/AsmParser/X86AsmParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/AsmParser/X86AsmParser.cpp?rev=179393&r1=179392&r2=179393&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/AsmParser/X86AsmParser.cpp (original)
+++ llvm/trunk/lib/Target/X86/AsmParser/X86AsmParser.cpp Fri Apr 12 13:21:18 2013
@@ -67,7 +67,9 @@ private:
                                          StringRef &Identifier);
   X86Operand *ParseMemOperand(unsigned SegReg, SMLoc StartLoc);
 
-  X86Operand *CreateMemForInlineAsm(const MCExpr *Disp, SMLoc Start, SMLoc End,
+  X86Operand *CreateMemForInlineAsm(unsigned SegReg, const MCExpr *Disp,
+                                    unsigned BaseReg, unsigned IndexReg,
+                                    unsigned Scale, SMLoc Start, SMLoc End,
                                     SMLoc SizeDirLoc, unsigned Size,
                                     StringRef SymName);
 
@@ -851,15 +853,20 @@ class IntelBracExprStateMachine {
   IntelBracExprState State;
   unsigned BaseReg, IndexReg, TmpReg, Scale;
   int64_t Disp;
+  const MCExpr *Sym;
+  StringRef SymName;
   InfixCalculator IC;
 public:
   IntelBracExprStateMachine(MCAsmParser &parser, int64_t disp) :
-    State(IBES_PLUS), BaseReg(0), IndexReg(0), TmpReg(0), Scale(1), Disp(disp){}
+    State(IBES_PLUS), BaseReg(0), IndexReg(0), TmpReg(0), Scale(1), Disp(disp),
+    Sym(0) {}
 
   unsigned getBaseReg() { return BaseReg; }
   unsigned getIndexReg() { return IndexReg; }
   unsigned getScale() { return Scale; }
-  int64_t getDisp() { return Disp + IC.execute(); }
+  const MCExpr *getSym() { return Sym; }
+  StringRef getSymName() { return SymName; }
+  int64_t getImmDisp() { return Disp + IC.execute(); }
   bool isValidEndState() { return State == IBES_RBRAC; }
 
   void onPlus() {
@@ -936,7 +943,7 @@ public:
       break;
     }
   }
-  void onDispExpr() {
+  void onDispExpr(const MCExpr *SymRef, StringRef SymRefName) {
     switch (State) {
     default:
       State = IBES_ERROR;
@@ -944,6 +951,8 @@ public:
     case IBES_PLUS:
     case IBES_MINUS:
       State = IBES_INTEGER;
+      Sym = SymRef;
+      SymName = SymRefName;
       IC.pushOperand(IC_IMM);
       break;
     }
@@ -1070,17 +1079,19 @@ public:
   }
 };
 
-X86Operand *X86AsmParser::CreateMemForInlineAsm(const MCExpr *Disp, SMLoc Start,
-                                                SMLoc End, SMLoc SizeDirLoc,
-                                                unsigned Size, StringRef SymName) {
+X86Operand *
+X86AsmParser::CreateMemForInlineAsm(unsigned SegReg, const MCExpr *Disp,
+                                    unsigned BaseReg, unsigned IndexReg,
+                                    unsigned Scale, SMLoc Start, SMLoc End,
+                                    SMLoc SizeDirLoc, unsigned Size,
+                                    StringRef SymName) {
   bool NeedSizeDir = false;
-  bool IsVarDecl = false;
-
   if (const MCSymbolRefExpr *SymRef = dyn_cast<MCSymbolRefExpr>(Disp)) {
     const MCSymbol &Sym = SymRef->getSymbol();
     // FIXME: The SemaLookup will fail if the name is anything other then an
     // identifier.
     // FIXME: Pass a valid SMLoc.
+    bool IsVarDecl = false;
     unsigned tLength, tSize, tType;
     SemaCallback->LookupInlineAsmIdentifier(Sym.getName(), NULL, tLength, tSize,
                                             tType, IsVarDecl);
@@ -1088,16 +1099,15 @@ X86Operand *X86AsmParser::CreateMemForIn
       Size = tType * 8; // Size is in terms of bits in this context.
       NeedSizeDir = Size > 0;
     }
-  }
-
-  // If this is not a VarDecl then assume it is a FuncDecl or some other label
-  // reference.  We need an 'r' constraint here, so we need to create register
-  // operand to ensure proper matching.  Just pick a GPR based on the size of
-  // a pointer.
-  if (!IsVarDecl) {
-    unsigned RegNo = is64BitMode() ? X86::RBX : X86::EBX;
-    return X86Operand::CreateReg(RegNo, Start, End, /*AddressOf=*/true, SMLoc(),
-      SymName);
+    // If this is not a VarDecl then assume it is a FuncDecl or some other label
+    // reference.  We need an 'r' constraint here, so we need to create register
+    // operand to ensure proper matching.  Just pick a GPR based on the size of
+    // a pointer.
+    if (!IsVarDecl) {
+      unsigned RegNo = is64BitMode() ? X86::RBX : X86::EBX;
+      return X86Operand::CreateReg(RegNo, Start, End, /*AddressOf=*/true,
+                                   SMLoc(), SymName);
+    }
   }
 
   if (NeedSizeDir)
@@ -1105,10 +1115,11 @@ X86Operand *X86AsmParser::CreateMemForIn
                                                 /*Len*/0, Size));  
 
   // When parsing inline assembly we set the base register to a non-zero value
-  // as we don't know the actual value at this time.  This is necessary to
+  // if we don't know the actual value at this time.  This is necessary to
   // get the matching correct in some cases.
-  return X86Operand::CreateMem(/*SegReg*/0, Disp, /*BaseReg*/1, /*IndexReg*/0,
-                               /*Scale*/1, Start, End, Size, SymName);
+  BaseReg = BaseReg ? BaseReg : 1;
+  return X86Operand::CreateMem(SegReg, Disp, BaseReg, IndexReg, Scale, Start,
+                               End, Size, SymName);
 }
 
 X86Operand *X86AsmParser::ParseIntelBracExpression(unsigned SegReg,
@@ -1118,12 +1129,12 @@ X86Operand *X86AsmParser::ParseIntelBrac
   const AsmToken &Tok = Parser.getTok();
   SMLoc Start = Tok.getLoc(), End = Tok.getEndLoc();
 
-  // Eat '['
   if (getLexer().isNot(AsmToken::LBrac))
     return ErrorOperand(Start, "Expected '[' token!");
-  Parser.Lex();
+  Parser.Lex(); // Eat '['
 
   unsigned TmpReg = 0;
+  SMLoc StartInBrac = Tok.getLoc();
 
   // Try to handle '[' 'Symbol' ']'
   if (getLexer().is(AsmToken::Identifier)) {
@@ -1148,8 +1159,9 @@ X86Operand *X86AsmParser::ParseIntelBrac
       Parser.Lex(); // Eat ']'
       if (!isParsingInlineAsm())
         return X86Operand::CreateMem(Disp, Start, End, Size);
-      return CreateMemForInlineAsm(Disp, Start, End, SizeDirLoc, Size,
-                                   Identifier);
+      return CreateMemForInlineAsm(/*SegReg=*/0, Disp, /*BaseReg=*/0,
+                                   /*IndexReg=*/0, /*Scale*/1, Start, End,
+                                   SizeDirLoc, Size, Identifier);
     }
   }
 
@@ -1164,7 +1176,6 @@ X86Operand *X86AsmParser::ParseIntelBrac
   if (TmpReg)
     SM.onRegister(TmpReg);
 
-  const MCExpr *Disp = 0;
   while (!Done) {
     bool UpdateLocLex = true;
 
@@ -1182,14 +1193,17 @@ X86Operand *X86AsmParser::ParseIntelBrac
       return ErrorOperand(Tok.getLoc(), "Unexpected token!");
     }
     case AsmToken::Identifier: {
-      // This could be a register or a displacement expression.
-      SMLoc Loc = Tok.getLoc();
-      if(!ParseRegister(TmpReg, Loc, End)) {
+      // This could be a register or a symbolic displacement.
+      unsigned TmpReg;
+      const MCExpr *Disp = 0;
+      AsmToken IdentTok = Parser.getTok();
+      SMLoc IdentLoc = IdentTok.getLoc();
+      if(!ParseRegister(TmpReg, IdentLoc, End)) {
         SM.onRegister(TmpReg);
         UpdateLocLex = false;
         break;
       } else if (!getParser().parsePrimaryExpr(Disp, End)) {
-        SM.onDispExpr();
+        SM.onDispExpr(Disp, IdentTok.getString());
         UpdateLocLex = false;
         break;
       }
@@ -1215,14 +1229,58 @@ X86Operand *X86AsmParser::ParseIntelBrac
       Parser.Lex(); // Consume the token.
     }
   }
-  if (isParsingInlineAsm() && Disp && isa<MCSymbolRefExpr>(Disp)) {
-    // Remove the '[' and ']' from the IR string.
-    InstInfo->AsmRewrites->push_back(AsmRewrite(AOK_Skip, Start, 1));
-    InstInfo->AsmRewrites->push_back(AsmRewrite(AOK_Skip, End, 1));
-  }
 
-  if (!Disp)
-    Disp = MCConstantExpr::Create(SM.getDisp(), getContext());
+  const MCExpr *Disp;
+  if (const MCExpr *Sym = SM.getSym()) {
+    Disp = Sym;
+
+    if (isParsingInlineAsm()) {
+      // Remove the '[' and ']' from the IR string.
+      InstInfo->AsmRewrites->push_back(AsmRewrite(AOK_Skip, Start, 1));
+      InstInfo->AsmRewrites->push_back(AsmRewrite(AOK_Skip, End, 1));
+
+      // If ImmDisp is non-zero, then we parsed a displacement before the
+      // bracketed expression (i.e., ImmDisp [ BaseReg + Scale*IndexReg + Disp ])
+      uint64_t FinalImmDisp = SM.getImmDisp();
+      if (ImmDisp && ImmDisp != FinalImmDisp) {
+        // If ImmDisp doesn't match the displacement computed by the state machine
+        // then we have an additional displacement in the bracketed expression.
+        
+      } else if (FinalImmDisp) {
+        // We have a symbolic and an immediate displacement, but no displacement
+        // before the bracketed expression.
+        
+        // Put the immediate displacement before the bracketed expression.
+        InstInfo->AsmRewrites->push_back(AsmRewrite(AOK_Imm, Start, 0,
+                                                    FinalImmDisp));
+      }
+      // Remove all the ImmPrefix rewrites within the brackets.
+      for (SmallVectorImpl<AsmRewrite>::iterator
+             I = InstInfo->AsmRewrites->begin(),
+             E = InstInfo->AsmRewrites->end(); I != E; ++I) {
+        if ((*I).Loc.getPointer() < StartInBrac.getPointer())
+          continue;
+        if ((*I).Kind == AOK_ImmPrefix)
+          (*I).Kind = AOK_Delete;
+      }
+      StringRef SymName = SM.getSymName();
+      const char *SymLocPtr = SymName.data();
+      // Skip everything before the symbol.        
+      if (unsigned Len = SymLocPtr - StartInBrac.getPointer()) {
+        assert(Len > 0 && "Expected a non-negative length.");
+        InstInfo->AsmRewrites->push_back(AsmRewrite(AOK_Skip, StartInBrac, Len));
+      }
+      // Skip everything after the symbol.
+      if (unsigned Len = End.getPointer() - (SymLocPtr + SymName.size())) {
+        SMLoc Loc = SMLoc::getFromPointer(SymLocPtr + SymName.size());
+        assert(Len > 0 && "Expected a non-negative length.");
+        InstInfo->AsmRewrites->push_back(AsmRewrite(AOK_Skip, Loc, Len));
+      }
+    }
+  } else {
+    // An immediate displacement only.
+    Disp = MCConstantExpr::Create(SM.getImmDisp(), getContext());
+  }
 
   // Parse the dot operator (e.g., [ebx].foo.bar).
   if (Tok.getString().startswith(".")) {
@@ -1238,6 +1296,11 @@ X86Operand *X86AsmParser::ParseIntelBrac
 
   int BaseReg = SM.getBaseReg();
   int IndexReg = SM.getIndexReg();
+  int Scale = SM.getScale();
+
+  if (isParsingInlineAsm())
+    return CreateMemForInlineAsm(SegReg, Disp, BaseReg, IndexReg, Scale, Start,
+                                 End, SizeDirLoc, Size, SM.getSymName());
 
   // handle [-42]
   if (!BaseReg && !IndexReg) {
@@ -1246,8 +1309,6 @@ X86Operand *X86AsmParser::ParseIntelBrac
     else
       return X86Operand::CreateMem(SegReg, Disp, 0, 0, 1, Start, End, Size);
   }
-
-  int Scale = SM.getScale();
   return X86Operand::CreateMem(SegReg, Disp, BaseReg, IndexReg, Scale, Start,
                                End, Size);
 }
@@ -1345,7 +1406,8 @@ X86Operand *X86AsmParser::ParseIntelMemO
   if (X86Operand *Err = ParseIntelVarWithQualifier(Disp, Identifier))
     return Err;
 
-  return CreateMemForInlineAsm(Disp, Start, End, Start, Size, Identifier);
+  return CreateMemForInlineAsm(/*SegReg=*/0, Disp, /*BaseReg=*/0,/*IndexReg=*/0,
+                               /*Scale=*/1, Start, End, Start, Size,Identifier);
 }
 
 /// Parse the '.' operator.





More information about the llvm-commits mailing list