From 11c42f2d2caa9b85885137fad1fefd3ac01155b7 Mon Sep 17 00:00:00 2001 From: Chad Rosier Date: Fri, 26 Oct 2012 18:04:20 +0000 Subject: [PATCH] [ms-inline asm] Add support for the TYPE operator. Part of rdar://12576868 llvm-svn: 166790 --- llvm/include/llvm/MC/MCParser/MCParsedAsmOperand.h | 6 +++ llvm/include/llvm/MC/MCTargetAsmParser.h | 18 ++++---- llvm/lib/MC/MCParser/AsmParser.cpp | 15 ++++-- 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 89b0a1f..60e7887 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 8383723..483a80b 100644 --- a/llvm/include/llvm/MC/MCTargetAsmParser.h +++ b/llvm/include/llvm/MC/MCTargetAsmParser.h @@ -22,13 +22,15 @@ class MCInst; template 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 0a65720..e8a87b0 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 a3e90af..87abfd2 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(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)) { -- 2.7.4