[ms-inline asm] Add support for the 'SIZE' and 'LENGTH' operators.

Part of rdar://12576868


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@172743 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chad Rosier
2013-01-17 19:21:48 +00:00
parent 3389dbcd24
commit 505bca3617
3 changed files with 49 additions and 37 deletions

View File

@@ -35,7 +35,9 @@ class MCAsmParserSemaCallback {
public: public:
virtual ~MCAsmParserSemaCallback(); virtual ~MCAsmParserSemaCallback();
virtual void *LookupInlineAsmIdentifier(StringRef Name, void *Loc, virtual void *LookupInlineAsmIdentifier(StringRef Name, void *Loc,
unsigned &Size, bool &IsVarDecl) = 0; unsigned &Length, unsigned &Size,
unsigned &Type, bool &IsVarDecl) = 0;
virtual bool LookupInlineAsmField(StringRef Base, StringRef Member, virtual bool LookupInlineAsmField(StringRef Base, StringRef Member,
unsigned &Offset) = 0; unsigned &Offset) = 0;
}; };

View File

@@ -3956,10 +3956,10 @@ bool AsmParser::ParseMSInlineAsm(void *AsmLoc, std::string &AsmString,
} }
// Expr/Input or Output. // Expr/Input or Output.
unsigned Size;
bool IsVarDecl; bool IsVarDecl;
unsigned Length, Size, Type;
void *OpDecl = SI.LookupInlineAsmIdentifier(Operand->getName(), AsmLoc, void *OpDecl = SI.LookupInlineAsmIdentifier(Operand->getName(), AsmLoc,
Size, IsVarDecl); Length, Size, Type, IsVarDecl);
if (OpDecl) { if (OpDecl) {
bool isOutput = (i == 1) && Desc.mayStore(); bool isOutput = (i == 1) && Desc.mayStore();
if (Operand->isMem() && Operand->needSizeDirective()) if (Operand->isMem() && Operand->needSizeDirective())

View File

@@ -57,7 +57,7 @@ private:
X86Operand *ParseATTOperand(); X86Operand *ParseATTOperand();
X86Operand *ParseIntelOperand(); X86Operand *ParseIntelOperand();
X86Operand *ParseIntelOffsetOfOperator(SMLoc StartLoc); X86Operand *ParseIntelOffsetOfOperator(SMLoc StartLoc);
X86Operand *ParseIntelTypeOperator(SMLoc StartLoc); X86Operand *ParseIntelOperator(SMLoc StartLoc, unsigned OpKind);
X86Operand *ParseIntelMemOperand(unsigned SegReg, SMLoc StartLoc); X86Operand *ParseIntelMemOperand(unsigned SegReg, SMLoc StartLoc);
X86Operand *ParseIntelBracExpression(unsigned SegReg, unsigned Size); X86Operand *ParseIntelBracExpression(unsigned SegReg, unsigned Size);
X86Operand *ParseMemOperand(unsigned SegReg, SMLoc StartLoc); X86Operand *ParseMemOperand(unsigned SegReg, SMLoc StartLoc);
@@ -1043,11 +1043,11 @@ X86Operand *X86AsmParser::ParseIntelMemOperand(unsigned SegReg, SMLoc Start) {
// FIXME: The SemaLookup will fail if the name is anything other then an // FIXME: The SemaLookup will fail if the name is anything other then an
// identifier. // identifier.
// FIXME: Pass a valid SMLoc. // FIXME: Pass a valid SMLoc.
unsigned tSize; unsigned tLength, tSize, tType;
SemaCallback->LookupInlineAsmIdentifier(Sym.getName(), NULL, tSize, SemaCallback->LookupInlineAsmIdentifier(Sym.getName(), NULL, tLength,
IsVarDecl); tSize, tType, IsVarDecl);
if (!Size) if (!Size)
Size = tSize; Size = tType * 8; // Size is in terms of bits in this context.
NeedSizeDir = Size > 0; NeedSizeDir = Size > 0;
} }
} }
@@ -1148,10 +1148,19 @@ X86Operand *X86AsmParser::ParseIntelOffsetOfOperator(SMLoc Start) {
OffsetOfLoc); OffsetOfLoc);
} }
/// Parse the 'TYPE' operator. The TYPE operator returns the size of a C or enum IntelOperatorKind {
/// C++ type or variable. If the variable is an array, TYPE returns the size of IOK_LENGTH,
/// a single element of the array. IOK_SIZE,
X86Operand *X86AsmParser::ParseIntelTypeOperator(SMLoc Start) { IOK_TYPE
};
/// Parse the 'LENGTH', 'TYPE' and 'SIZE' operators. The LENGTH operator
/// returns the number of elements in an array. It returns the value 1 for
/// non-array variables. The SIZE operator returns the size of a C or C++
/// variable. A variable's size is the product of its LENGTH and TYPE. 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.
X86Operand *X86AsmParser::ParseIntelOperator(SMLoc Start, unsigned OpKind) {
SMLoc TypeLoc = Start; SMLoc TypeLoc = Start;
Parser.Lex(); // Eat offset. Parser.Lex(); // Eat offset.
Start = Parser.getTok().getLoc(); Start = Parser.getTok().getLoc();
@@ -1162,50 +1171,51 @@ X86Operand *X86AsmParser::ParseIntelTypeOperator(SMLoc Start) {
if (getParser().ParseExpression(Val, End)) if (getParser().ParseExpression(Val, End))
return 0; return 0;
unsigned Size = 0; unsigned Length = 0, Size = 0, Type = 0;
if (const MCSymbolRefExpr *SymRef = dyn_cast<MCSymbolRefExpr>(Val)) { if (const MCSymbolRefExpr *SymRef = dyn_cast<MCSymbolRefExpr>(Val)) {
const MCSymbol &Sym = SymRef->getSymbol(); const MCSymbol &Sym = SymRef->getSymbol();
// FIXME: The SemaLookup will fail if the name is anything other then an // FIXME: The SemaLookup will fail if the name is anything other then an
// identifier. // identifier.
// FIXME: Pass a valid SMLoc. // FIXME: Pass a valid SMLoc.
bool IsVarDecl; bool IsVarDecl;
if (!SemaCallback->LookupInlineAsmIdentifier(Sym.getName(), NULL, Size, if (!SemaCallback->LookupInlineAsmIdentifier(Sym.getName(), NULL, Length,
IsVarDecl)) Size, Type, IsVarDecl))
return ErrorOperand(Start, "Unable to lookup TYPE of expr!"); return ErrorOperand(Start, "Unable to lookup TYPE of expr!");
}
Size /= 8; // Size is in terms of bits, but we want bytes in the context. unsigned CVal;
switch(OpKind) {
default: llvm_unreachable("Unexpected operand kind!");
case IOK_LENGTH: CVal = Length; break;
case IOK_SIZE: CVal = Size; break;
case IOK_TYPE: CVal = Type; break;
} }
// Rewrite the type operator and the C or C++ type or variable in terms of an // Rewrite the type operator and the C or C++ type or variable in terms of an
// immediate. E.g. TYPE foo -> $$4 // immediate. E.g. TYPE foo -> $$4
unsigned Len = End.getPointer() - TypeLoc.getPointer(); unsigned Len = End.getPointer() - TypeLoc.getPointer();
InstInfo->AsmRewrites->push_back(AsmRewrite(AOK_Imm, TypeLoc, Len, Size)); InstInfo->AsmRewrites->push_back(AsmRewrite(AOK_Imm, TypeLoc, Len, CVal));
const MCExpr *Imm = MCConstantExpr::Create(Size, getContext()); const MCExpr *Imm = MCConstantExpr::Create(CVal, getContext());
return X86Operand::CreateImm(Imm, Start, End, /*NeedAsmRewrite*/false); return X86Operand::CreateImm(Imm, Start, End, /*NeedAsmRewrite*/false);
} }
X86Operand *X86AsmParser::ParseIntelOperand() { X86Operand *X86AsmParser::ParseIntelOperand() {
SMLoc Start = Parser.getTok().getLoc(), End; SMLoc Start = Parser.getTok().getLoc(), End;
// offset operator.
StringRef AsmTokStr = Parser.getTok().getString(); StringRef AsmTokStr = Parser.getTok().getString();
if ((AsmTokStr == "offset" || AsmTokStr == "OFFSET") &&
isParsingInlineAsm())
return ParseIntelOffsetOfOperator(Start);
// Type directive. // Offset, length, type and size operators.
if ((AsmTokStr == "type" || AsmTokStr == "TYPE") && if (isParsingInlineAsm()) {
isParsingInlineAsm()) if (AsmTokStr == "offset" || AsmTokStr == "OFFSET")
return ParseIntelTypeOperator(Start); return ParseIntelOffsetOfOperator(Start);
if (AsmTokStr == "length" || AsmTokStr == "LENGTH")
return ParseIntelOperator(Start, IOK_LENGTH);
if (AsmTokStr == "size" || AsmTokStr == "SIZE")
return ParseIntelOperator(Start, IOK_SIZE);
if (AsmTokStr == "type" || AsmTokStr == "TYPE")
return ParseIntelOperator(Start, IOK_TYPE);
}
// Unsupported directives. // Immediate.
if (isParsingIntelSyntax() &&
(AsmTokStr == "size" || AsmTokStr == "SIZE" ||
AsmTokStr == "length" || AsmTokStr == "LENGTH"))
return ErrorOperand(Start, "Unsupported directive!");
// immediate.
if (getLexer().is(AsmToken::Integer) || getLexer().is(AsmToken::Real) || if (getLexer().is(AsmToken::Integer) || getLexer().is(AsmToken::Real) ||
getLexer().is(AsmToken::Minus)) { getLexer().is(AsmToken::Minus)) {
const MCExpr *Val; const MCExpr *Val;
@@ -1214,7 +1224,7 @@ X86Operand *X86AsmParser::ParseIntelOperand() {
} }
} }
// register // Register.
unsigned RegNo = 0; unsigned RegNo = 0;
if (!ParseRegister(RegNo, Start, End)) { if (!ParseRegister(RegNo, Start, End)) {
// If this is a segment register followed by a ':', then this is the start // If this is a segment register followed by a ':', then this is the start
@@ -1226,7 +1236,7 @@ X86Operand *X86AsmParser::ParseIntelOperand() {
return ParseIntelMemOperand(RegNo, Start); return ParseIntelMemOperand(RegNo, Start);
} }
// mem operand // Memory operand.
return ParseIntelMemOperand(0, Start); return ParseIntelMemOperand(0, Start);
} }