[ms-inline-asm] Implement align directive (which is roughly equivalent to .align).

Also, allow _EMIT and __EMIT for the emit directive.  We already do the same
for TYPE, SIZE, and LENGTH.
rdar://13200215


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@175008 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chad Rosier 2013-02-12 21:33:51 +00:00
parent dc08bfbd56
commit 469b144f1c
2 changed files with 44 additions and 9 deletions

View File

@ -22,6 +22,7 @@ class MCInst;
template <typename T> class SmallVectorImpl; template <typename T> class SmallVectorImpl;
enum AsmRewriteKind { enum AsmRewriteKind {
AOK_Align, // Rewrite align as .align.
AOK_DotOperator, // Rewrite a dot operator expression as an immediate. AOK_DotOperator, // Rewrite a dot operator expression as an immediate.
// E.g., [eax].foo.bar -> [eax].8 // E.g., [eax].foo.bar -> [eax].8
AOK_Emit, // Rewrite _emit as .byte. AOK_Emit, // Rewrite _emit as .byte.

View File

@ -443,9 +443,12 @@ private:
bool ParseDirectiveIrpc(SMLoc DirectiveLoc); // ".irpc" bool ParseDirectiveIrpc(SMLoc DirectiveLoc); // ".irpc"
bool ParseDirectiveEndr(SMLoc DirectiveLoc); // ".endr" bool ParseDirectiveEndr(SMLoc DirectiveLoc); // ".endr"
// "_emit" // "_emit" or "__emit"
bool ParseDirectiveEmit(SMLoc DirectiveLoc, ParseStatementInfo &Info, bool ParseDirectiveMSEmit(SMLoc DirectiveLoc, ParseStatementInfo &Info,
size_t len); size_t Len);
// "align"
bool ParseDirectiveMSAlign(SMLoc DirectiveLoc, ParseStatementInfo &Info);
void initializeDirectiveKindMap(); void initializeDirectiveKindMap();
}; };
@ -1447,9 +1450,14 @@ bool AsmParser::ParseStatement(ParseStatementInfo &Info) {
return Error(IDLoc, "unknown directive"); return Error(IDLoc, "unknown directive");
} }
// _emit or __emit // __asm _emit or __asm __emit
if (ParsingInlineAsm && (IDVal == "_emit" || IDVal == "__emit")) if (ParsingInlineAsm && (IDVal == "_emit" || IDVal == "__emit" ||
return ParseDirectiveEmit(IDLoc, Info, IDVal.size()); IDVal == "_EMIT" || IDVal == "__EMIT"))
return ParseDirectiveMSEmit(IDLoc, Info, IDVal.size());
// __asm align
if (ParsingInlineAsm && (IDVal == "align" || IDVal == "ALIGN"))
return ParseDirectiveMSAlign(IDLoc, Info);
CheckForValidSection(); CheckForValidSection();
@ -3989,7 +3997,7 @@ bool AsmParser::ParseDirectiveEndr(SMLoc DirectiveLoc) {
return false; return false;
} }
bool AsmParser::ParseDirectiveEmit(SMLoc IDLoc, ParseStatementInfo &Info, size_t len) { bool AsmParser::ParseDirectiveMSEmit(SMLoc IDLoc, ParseStatementInfo &Info, size_t Len) {
const MCExpr *Value; const MCExpr *Value;
SMLoc ExprLoc = getLexer().getLoc(); SMLoc ExprLoc = getLexer().getLoc();
if (ParseExpression(Value)) if (ParseExpression(Value))
@ -4001,7 +4009,23 @@ bool AsmParser::ParseDirectiveEmit(SMLoc IDLoc, ParseStatementInfo &Info, size_t
if (!isUIntN(8, IntValue) && !isIntN(8, IntValue)) if (!isUIntN(8, IntValue) && !isIntN(8, IntValue))
return Error(ExprLoc, "literal value out of range for directive"); return Error(ExprLoc, "literal value out of range for directive");
Info.AsmRewrites->push_back(AsmRewrite(AOK_Emit, IDLoc, len)); Info.AsmRewrites->push_back(AsmRewrite(AOK_Emit, IDLoc, Len));
return false;
}
bool AsmParser::ParseDirectiveMSAlign(SMLoc IDLoc, ParseStatementInfo &Info) {
const MCExpr *Value;
SMLoc ExprLoc = getLexer().getLoc();
if (ParseExpression(Value))
return true;
const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
if (!MCE)
return Error(ExprLoc, "unexpected expression in align");
uint64_t IntValue = MCE->getValue();
if (!isPowerOf2_64(IntValue))
return Error(ExprLoc, "literal value not a power of two greater then zero");
Info.AsmRewrites->push_back(AsmRewrite(AOK_Align, IDLoc, 5, Log2_64(IntValue)));
return false; return false;
} }
@ -4133,6 +4157,7 @@ bool AsmParser::ParseMSInlineAsm(void *AsmLoc, std::string &AsmString,
I = AsmStrRewrites.begin(), E = AsmStrRewrites.end(); I != E; ++I) { I = AsmStrRewrites.begin(), E = AsmStrRewrites.end(); I != E; ++I) {
const char *Loc = (*I).Loc.getPointer(); const char *Loc = (*I).Loc.getPointer();
unsigned AdditionalSkip = 0;
AsmRewriteKind Kind = (*I).Kind; AsmRewriteKind Kind = (*I).Kind;
// Emit everything up to the immediate/expression. If the previous rewrite // Emit everything up to the immediate/expression. If the previous rewrite
@ -4180,6 +4205,15 @@ bool AsmParser::ParseMSInlineAsm(void *AsmLoc, std::string &AsmString,
case AOK_Emit: case AOK_Emit:
OS << ".byte"; OS << ".byte";
break; break;
case AOK_Align: {
unsigned Val = (*I).Val;
OS << ".align " << Val;
// Skip the original immediate.
assert (Val < 10 && "Expected alignment less then 2^10.");
AdditionalSkip = (Val < 4) ? 2 : Val < 7 ? 3 : 4;
break;
}
case AOK_DotOperator: case AOK_DotOperator:
OS << (*I).Val; OS << (*I).Val;
break; break;
@ -4187,7 +4221,7 @@ bool AsmParser::ParseMSInlineAsm(void *AsmLoc, std::string &AsmString,
// Skip the original expression. // Skip the original expression.
if (Kind != AOK_SizeDirective) if (Kind != AOK_SizeDirective)
Start = Loc + (*I).Len; Start = Loc + (*I).Len + AdditionalSkip;
} }
// Emit the remainder of the asm string. // Emit the remainder of the asm string.