summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChad Rosier <mcrosier@apple.com>2012-10-19 20:57:14 +0000
committerChad Rosier <mcrosier@apple.com>2012-10-19 20:57:14 +0000
commit96d58e64cfe88356f8be4ce622b829fbd9fb5908 (patch)
treeaa5883e266315318a6b7835bbd46cb0652797d13
parente2b95ebfb031c3defc75417521e89ef289a94171 (diff)
downloadllvm-96d58e64cfe88356f8be4ce622b829fbd9fb5908.tar.gz
llvm-96d58e64cfe88356f8be4ce622b829fbd9fb5908.tar.bz2
llvm-96d58e64cfe88356f8be4ce622b829fbd9fb5908.tar.xz
[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
-rw-r--r--include/llvm/MC/MCParser/MCParsedAsmOperand.h5
-rw-r--r--lib/MC/MCParser/AsmParser.cpp46
-rw-r--r--lib/Target/X86/AsmParser/X86AsmParser.cpp33
3 files changed, 70 insertions, 14 deletions
diff --git a/include/llvm/MC/MCParser/MCParsedAsmOperand.h b/include/llvm/MC/MCParser/MCParsedAsmOperand.h
index 280145bfbc..7d0914ebb4 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 1573799433..6669780c7d 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<struct AsmOpRewrite>::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 454664e3ed..70f6ef766f 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<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.
+ SemaCallback->LookupInlineAsmIdentifier(Sym.getName(), NULL, Size);
+ NeedSizeDir = Size > 0;
+ }
+ }
+ return X86Operand::CreateMem(Disp, Start, End, Size, NeedSizeDir);
}
X86Operand *X86AsmParser::ParseIntelOperand() {