diff options
| -rw-r--r-- | llvm/include/llvm/MC/MCParser/MCParsedAsmOperand.h | 6 | ||||
| -rw-r--r-- | llvm/include/llvm/MC/MCTargetAsmParser.h | 18 | ||||
| -rw-r--r-- | llvm/lib/MC/MCParser/AsmParser.cpp | 15 | ||||
| -rw-r--r-- | llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp | 53 | 
4 files changed, 78 insertions, 14 deletions
diff --git a/llvm/include/llvm/MC/MCParser/MCParsedAsmOperand.h b/llvm/include/llvm/MC/MCParser/MCParsedAsmOperand.h index 89b0a1f47b6..60e7887a539 100644 --- a/llvm/include/llvm/MC/MCParser/MCParsedAsmOperand.h +++ b/llvm/include/llvm/MC/MCParser/MCParsedAsmOperand.h @@ -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. diff --git a/llvm/include/llvm/MC/MCTargetAsmParser.h b/llvm/include/llvm/MC/MCTargetAsmParser.h index 838372380aa..483a80b3b59 100644 --- a/llvm/include/llvm/MC/MCTargetAsmParser.h +++ b/llvm/include/llvm/MC/MCTargetAsmParser.h @@ -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) {}  }; diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp index 0a657205493..e8a87b061ee 100644 --- a/llvm/lib/MC/MCParser/AsmParser.cpp +++ b/llvm/lib/MC/MCParser/AsmParser.cpp @@ -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 << '$'; diff --git a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp index a3e90af71ad..87abfd22413 100644 --- a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp +++ b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -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)) {  | 

