mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-25 04:39:44 +00:00
[ms-inline asm] Add support for the TYPE operator.
Part of rdar://12576868 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@166790 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
8999f4777b
commit
efcb3d9c1c
@ -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.
|
||||
|
@ -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) {}
|
||||
};
|
||||
|
||||
|
@ -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 << '$';
|
||||
|
@ -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)) {
|
||||
|
Loading…
Reference in New Issue
Block a user