[ms-inline asm] Add support for the TYPE operator.
authorChad Rosier <mcrosier@apple.com>
Fri, 26 Oct 2012 18:04:20 +0000 (18:04 +0000)
committerChad Rosier <mcrosier@apple.com>
Fri, 26 Oct 2012 18:04:20 +0000 (18:04 +0000)
Part of rdar://12576868

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

include/llvm/MC/MCParser/MCParsedAsmOperand.h
include/llvm/MC/MCTargetAsmParser.h
lib/MC/MCParser/AsmParser.cpp
lib/Target/X86/AsmParser/X86AsmParser.cpp

index 89b0a1f47b6fbfa970bdd876acfb7e2930a32517..60e7887a53963925478a172996d9bbded5532b8e 100644 (file)
@@ -64,6 +64,12 @@ public:
   /// getEndLoc - Get the location of the last token of this operand.
   virtual SMLoc getEndLoc() const = 0;
 
+  /// needAsmRewrite - AsmRewrites happen in both the target-independent and
+  /// target-dependent parsers.  The target-independent parser calls this
+  /// function to determine if the target-dependent parser has already taken
+  /// care of the rewrites.  Only valid when parsing MS-style inline assembly.
+  virtual bool needAsmRewrite() const { return true; }
+
   /// isOffsetOf - Do we need to emit code to get the offset of the variable,
   /// rather then the value of the variable?   Only valid when parsing MS-style
   /// inline assembly.
index 838372380aa47fbf223913df1bdf81d67247e55d..483a80b3b595938d953df54e54eb87927eb3d351 100644 (file)
@@ -22,13 +22,15 @@ class MCInst;
 template <typename T> class SmallVectorImpl;
 
 enum AsmRewriteKind {
-   AOK_Imm,
-   AOK_Input,
-   AOK_Output,
-   AOK_SizeDirective,
-   AOK_Emit,
-   AOK_Skip,
-   AOK_DotOperator
+  AOK_DotOperator,    // Rewrite a dot operator expression as an immediate.
+                      // E.g., [eax].foo.bar -> [eax].8
+  AOK_Emit,           // Rewrite _emit as .byte.
+  AOK_Imm,            // Rewrite as $$N.
+  AOK_ImmPrefix,      // Add $$ before a parsed Imm.
+  AOK_Input,          // Rewrite in terms of $N.
+  AOK_Output,         // Rewrite in terms of $N.
+  AOK_SizeDirective,  // Add a sizing directive (e.g., dword ptr).
+  AOK_Skip            // Skip emission (e.g., offset/type operators).
 };
 
 struct AsmRewrite {
@@ -37,7 +39,7 @@ struct AsmRewrite {
   unsigned Len;
   unsigned Val;
 public:
-  AsmRewrite(AsmRewriteKind kind, SMLoc loc, unsigned len, unsigned val = 0)
+  AsmRewrite(AsmRewriteKind kind, SMLoc loc, unsigned len = 0, unsigned val = 0)
     : Kind(kind), Loc(loc), Len(len), Val(val) {}
 };
 
index 0a657205493e47c83fa27b497f78332a7226f694..e8a87b061eeb3aa3237c5e828457f4d836a96f20 100644 (file)
@@ -3638,9 +3638,9 @@ bool AsmParser::ParseMSInlineAsm(void *AsmLoc, std::string &AsmString,
 
         // Immediate.
         if (Operand->isImm()) {
-          AsmStrRewrites.push_back(AsmRewrite(AOK_Imm,
-                                              Operand->getStartLoc(),
-                                              Operand->getNameLen()));
+          if (Operand->needAsmRewrite())
+            AsmStrRewrites.push_back(AsmRewrite(AOK_ImmPrefix,
+                                                Operand->getStartLoc()));
           continue;
         }
 
@@ -3665,7 +3665,8 @@ bool AsmParser::ParseMSInlineAsm(void *AsmLoc, std::string &AsmString,
           bool isOutput = (i == 1) && Desc.mayStore();
           if (!Operand->isOffsetOf() && Operand->needSizeDirective())
             AsmStrRewrites.push_back(AsmRewrite(AOK_SizeDirective,
-                                                Operand->getStartLoc(), 0,
+                                                Operand->getStartLoc(),
+                                                /*Len*/0,
                                                 Operand->getMemSize()));
           if (isOutput) {
             std::string Constraint = "=";
@@ -3743,7 +3744,11 @@ bool AsmParser::ParseMSInlineAsm(void *AsmLoc, std::string &AsmString,
     switch (Kind) {
     default: break;
     case AOK_Imm:
-      OS << Twine("$$") + StringRef(Loc, (*I).Len);
+      OS << Twine("$$");
+      OS << (*I).Val;
+      break;
+    case AOK_ImmPrefix:
+      OS << Twine("$$");
       break;
     case AOK_Input:
       OS << '$';
index a3e90af71ad9bd84fcd7bc982b10d6254343c514..87abfd22413e73dcfa4a48704ea5ae9728a8ff22 100644 (file)
@@ -57,6 +57,7 @@ private:
   X86Operand *ParseATTOperand();
   X86Operand *ParseIntelOperand();
   X86Operand *ParseIntelOffsetOfOperator(SMLoc StartLoc);
+  X86Operand *ParseIntelTypeOperator(SMLoc StartLoc);
   X86Operand *ParseIntelMemOperand(unsigned SegReg, SMLoc StartLoc);
   X86Operand *ParseIntelBracExpression(unsigned SegReg, unsigned Size);
   X86Operand *ParseMemOperand(unsigned SegReg, SMLoc StartLoc);
@@ -180,6 +181,7 @@ struct X86Operand : public MCParsedAsmOperand {
 
     struct {
       const MCExpr *Val;
+      bool NeedAsmRewrite;
     } Imm;
 
     struct {
@@ -228,6 +230,11 @@ struct X86Operand : public MCParsedAsmOperand {
     return Imm.Val;
   }
 
+  bool needAsmRewrite() const {
+    assert(Kind == Immediate && "Invalid access!");
+    return Imm.NeedAsmRewrite;
+  }
+
   const MCExpr *getMemDisp() const {
     assert(Kind == Memory && "Invalid access!");
     return Mem.Disp;
@@ -471,9 +478,11 @@ struct X86Operand : public MCParsedAsmOperand {
     return Res;
   }
 
-  static X86Operand *CreateImm(const MCExpr *Val, SMLoc StartLoc, SMLoc EndLoc){
+  static X86Operand *CreateImm(const MCExpr *Val, SMLoc StartLoc, SMLoc EndLoc,
+                               bool NeedRewrite = true){
     X86Operand *Res = new X86Operand(Immediate, StartLoc, EndLoc);
     Res->Imm.Val = Val;
+    Res->Imm.NeedAsmRewrite = NeedRewrite;
     return Res;
   }
 
@@ -896,6 +905,43 @@ X86Operand *X86AsmParser::ParseIntelOffsetOfOperator(SMLoc Start) {
   return X86Operand::CreateReg(RegNo, Start, End, OffsetOfLoc);
 }
 
+/// Parse the 'TYPE' operator.  The TYPE operator returns the size of a C or
+/// C++ type or variable. If the variable is an array, TYPE returns the size of
+/// a single element of the array.
+X86Operand *X86AsmParser::ParseIntelTypeOperator(SMLoc Start) {
+  SMLoc TypeLoc = Start;
+  Parser.Lex(); // Eat offset.
+  Start = Parser.getTok().getLoc();
+  assert (Parser.getTok().is(AsmToken::Identifier) && "Expected an identifier");
+
+  SMLoc End;
+  const MCExpr *Val;
+  if (getParser().ParseExpression(Val, End))
+    return 0;
+
+  End = Parser.getTok().getLoc();
+
+  unsigned Size = 0;
+  if (const MCSymbolRefExpr *SymRef = dyn_cast<MCSymbolRefExpr>(Val)) {
+    const MCSymbol &Sym = SymRef->getSymbol();
+    // FIXME: The SemaLookup will fail if the name is anything other then an
+    // identifier.
+    // FIXME: Pass a valid SMLoc.
+    if (!SemaCallback->LookupInlineAsmIdentifier(Sym.getName(), NULL, Size))
+      return ErrorOperand(Start, "Unable to lookup TYPE of expr.");
+
+    Size /= 8; // Size is in terms of bits, but we want bytes in the context.
+  }
+
+  // Rewrite the type operator and the C or C++ type or variable in terms of an
+  // immediate.  E.g. TYPE foo -> $$4
+  unsigned Len = End.getPointer() - TypeLoc.getPointer();
+  InstInfo->AsmRewrites->push_back(AsmRewrite(AOK_Imm, TypeLoc, Len, Size));
+
+  const MCExpr *Imm = MCConstantExpr::Create(Size, getContext());
+  return X86Operand::CreateImm(Imm, Start, End, /*NeedAsmRewrite*/false);
+}
+
 X86Operand *X86AsmParser::ParseIntelOperand() {
   SMLoc Start = Parser.getTok().getLoc(), End;
 
@@ -905,6 +951,11 @@ X86Operand *X86AsmParser::ParseIntelOperand() {
       isParsingInlineAsm())
     return ParseIntelOffsetOfOperator(Start);
 
+  // Type directive.
+  if ((Tok.getString() == "type" || Tok.getString() == "TYPE") &&
+      isParsingInlineAsm())
+    return ParseIntelTypeOperator(Start);
+
   // immediate.
   if (getLexer().is(AsmToken::Integer) || getLexer().is(AsmToken::Real) ||
       getLexer().is(AsmToken::Minus)) {