From 96d58e64cfe88356f8be4ce622b829fbd9fb5908 Mon Sep 17 00:00:00 2001 From: Chad Rosier Date: Fri, 19 Oct 2012 20:57:14 +0000 Subject: [PATCH] [ms-inline asm] Have the TargetParser callback to Sema to determine the size of a memory operand. Retain this information and then add the sizing directives to the IR. This allows the backend to do proper instruction selection. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@166316 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/MC/MCParser/MCParsedAsmOperand.h | 5 +++ lib/MC/MCParser/AsmParser.cpp | 46 ++++++++++++++++++++------- lib/Target/X86/AsmParser/X86AsmParser.cpp | 33 +++++++++++++++++-- 3 files changed, 70 insertions(+), 14 deletions(-) diff --git a/include/llvm/MC/MCParser/MCParsedAsmOperand.h b/include/llvm/MC/MCParser/MCParsedAsmOperand.h index 280145bfbc8..7d0914ebb49 100644 --- a/include/llvm/MC/MCParser/MCParsedAsmOperand.h +++ b/include/llvm/MC/MCParser/MCParsedAsmOperand.h @@ -57,12 +57,17 @@ public: /// isMem - Is this a memory operand? virtual bool isMem() const = 0; + virtual unsigned getMemSize() const { return 0; } /// getStartLoc - Get the location of the first token of this operand. virtual SMLoc getStartLoc() const = 0; /// getEndLoc - Get the location of the last token of this operand. virtual SMLoc getEndLoc() const = 0; + /// needSizeDirective - Do we need to emit a sizing directive for this + /// operand? Only valid when parsing MS-style inline assembly. + virtual bool needSizeDirective() const { return false; } + /// print - Print a debug representation of the operand to the given stream. virtual void print(raw_ostream &OS) const = 0; /// dump - Print to the debug stream. diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp index 15737994335..6669780c7db 100644 --- a/lib/MC/MCParser/AsmParser.cpp +++ b/lib/MC/MCParser/AsmParser.cpp @@ -3577,17 +3577,18 @@ namespace { enum AsmOpRewriteKind { AOK_Imm, AOK_Input, - AOK_Output + AOK_Output, + AOK_SizeDirective }; struct AsmOpRewrite { AsmOpRewriteKind Kind; SMLoc Loc; unsigned Len; - + unsigned Size; public: - AsmOpRewrite(AsmOpRewriteKind kind, SMLoc loc, unsigned len) - : Kind(kind), Loc(loc), Len(len) { } + AsmOpRewrite(AsmOpRewriteKind kind, SMLoc loc, unsigned len, unsigned size = 0) + : Kind(kind), Loc(loc), Len(len), Size(size) { } }; } @@ -3650,6 +3651,11 @@ bool AsmParser::ParseMSInlineAsm(void *AsmLoc, std::string &AsmString, Size); if (OpDecl) { bool isOutput = (i == 1) && Desc.mayStore(); + if (Operand->needSizeDirective()) + AsmStrRewrites.push_back(AsmOpRewrite(AOK_SizeDirective, + Operand->getStartLoc(), 0, + Operand->getMemSize())); + if (isOutput) { std::string Constraint = "="; ++InputIdx; @@ -3701,17 +3707,23 @@ bool AsmParser::ParseMSInlineAsm(void *AsmLoc, std::string &AsmString, // Build the IR assembly string. std::string AsmStringIR; + AsmOpRewriteKind PrevKind = AOK_Imm; raw_string_ostream OS(AsmStringIR); const char *Start = SrcMgr.getMemoryBuffer(0)->getBufferStart(); for (SmallVectorImpl::iterator I = AsmStrRewrites.begin(), E = AsmStrRewrites.end(); I != E; ++I) { const char *Loc = (*I).Loc.getPointer(); - - // Emit everything up to the immediate/expression. - OS << StringRef(Start, Loc - Start); - + + AsmOpRewriteKind Kind = (*I).Kind; + + // Emit everything up to the immediate/expression. If the previous rewrite + // was a size directive, then this has already been done. + if (PrevKind != AOK_SizeDirective) + OS << StringRef(Start, Loc - Start); + PrevKind = Kind; + // Rewrite expressions in $N notation. - switch ((*I).Kind) { + switch (Kind) { case AOK_Imm: OS << Twine("$$") + StringRef(Loc, (*I).Len); break; @@ -3723,10 +3735,22 @@ bool AsmParser::ParseMSInlineAsm(void *AsmLoc, std::string &AsmString, OS << '$'; OS << OutputIdx++; break; + case AOK_SizeDirective: + switch((*I).Size) { + default: break; + case 8: OS << "byte ptr "; break; + case 16: OS << "word ptr "; break; + case 32: OS << "dword ptr "; break; + case 64: OS << "qword ptr "; break; + case 80: OS << "xword ptr "; break; + case 128: OS << "xmmword ptr "; break; + case 256: OS << "ymmword ptr "; break; + } } - + // Skip the original expression. - Start = Loc + (*I).Len; + if (Kind != AOK_SizeDirective) + Start = Loc + (*I).Len; } // Emit the remainder of the asm string. diff --git a/lib/Target/X86/AsmParser/X86AsmParser.cpp b/lib/Target/X86/AsmParser/X86AsmParser.cpp index 454664e3ed1..70f6ef766f8 100644 --- a/lib/Target/X86/AsmParser/X86AsmParser.cpp +++ b/lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -11,6 +11,7 @@ #include "llvm/MC/MCTargetAsmParser.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSubtargetInfo.h" @@ -180,6 +181,7 @@ struct X86Operand : public MCParsedAsmOperand { unsigned IndexReg; unsigned Scale; unsigned Size; + bool NeedSizeDir; } Mem; }; @@ -312,6 +314,16 @@ struct X86Operand : public MCParsedAsmOperand { return isImmSExti64i32Value(CE->getValue()); } + unsigned getMemSize() const { + assert(Kind == Memory && "Invalid access!"); + return Mem.Size; + } + + bool needSizeDirective() const { + assert(Kind == Memory && "Invalid access!"); + return Mem.NeedSizeDir; + } + bool isMem() const { return Kind == Memory; } bool isMem8() const { return Kind == Memory && (!Mem.Size || Mem.Size == 8); @@ -451,7 +463,8 @@ struct X86Operand : public MCParsedAsmOperand { /// Create an absolute memory operand. static X86Operand *CreateMem(const MCExpr *Disp, SMLoc StartLoc, - SMLoc EndLoc, unsigned Size = 0) { + SMLoc EndLoc, unsigned Size = 0, + bool NeedSizeDir = false) { X86Operand *Res = new X86Operand(Memory, StartLoc, EndLoc); Res->Mem.SegReg = 0; Res->Mem.Disp = Disp; @@ -459,6 +472,7 @@ struct X86Operand : public MCParsedAsmOperand { Res->Mem.IndexReg = 0; Res->Mem.Scale = 1; Res->Mem.Size = Size; + Res->Mem.NeedSizeDir = NeedSizeDir; return Res; } @@ -466,7 +480,7 @@ struct X86Operand : public MCParsedAsmOperand { static X86Operand *CreateMem(unsigned SegReg, const MCExpr *Disp, unsigned BaseReg, unsigned IndexReg, unsigned Scale, SMLoc StartLoc, SMLoc EndLoc, - unsigned Size = 0) { + unsigned Size = 0, bool NeedSizeDir = false) { // We should never just have a displacement, that should be parsed as an // absolute memory operand. assert((SegReg || BaseReg || IndexReg) && "Invalid memory operand!"); @@ -481,6 +495,7 @@ struct X86Operand : public MCParsedAsmOperand { Res->Mem.IndexReg = IndexReg; Res->Mem.Scale = Scale; Res->Mem.Size = Size; + Res->Mem.NeedSizeDir = NeedSizeDir; return Res; } }; @@ -753,7 +768,19 @@ X86Operand *X86AsmParser::ParseIntelMemOperand(unsigned SegReg, SMLoc Start) { const MCExpr *Disp = MCConstantExpr::Create(0, getParser().getContext()); if (getParser().ParseExpression(Disp, End)) return 0; End = Parser.getTok().getLoc(); - return X86Operand::CreateMem(Disp, Start, End, Size); + + bool NeedSizeDir = false; + if (!Size && isParsingInlineAsm()) { + if (const MCSymbolRefExpr *SymRef = dyn_cast(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. + SemaCallback->LookupInlineAsmIdentifier(Sym.getName(), NULL, Size); + NeedSizeDir = Size > 0; + } + } + return X86Operand::CreateMem(Disp, Start, End, Size, NeedSizeDir); } X86Operand *X86AsmParser::ParseIntelOperand() { -- 2.11.0