[ms-inline asm] Add support for detecting simple ms-style inline asm. Simple

asm statements are those that don't reference variable names, function names,
and labels.

Add logic to generate a patched AsmString that will eventually be consumed by
the AsmParser.  No functional change at this point, so unfortunately no test
case.

llvm-svn: 161508
This commit is contained in:
Chad Rosier 2012-08-08 18:22:06 +00:00
parent e71b6c6b20
commit d12b7a64dc
1 changed files with 104 additions and 2 deletions

View File

@ -2747,6 +2747,99 @@ StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, bool IsSimple,
return Owned(NS);
}
// needSpaceAsmToken - This function handles whitespace around asm punctuation.
// Returns true if a space should be emitted.
//
// FIXME: This is replicated in ParseStmt.cpp. Maybe we should defer building
// the AsmString (i.e., non-patched AsmString) until Sema.
static inline bool needSpaceAsmToken(Token currTok) {
static Token prevTok;
// No need for space after prevToken.
switch(prevTok.getKind()) {
default:
break;
case tok::l_square:
case tok::r_square:
case tok::l_brace:
case tok::r_brace:
case tok::colon:
prevTok = currTok;
return false;
}
// No need for a space before currToken.
switch(currTok.getKind()) {
default:
break;
case tok::l_square:
case tok::r_square:
case tok::l_brace:
case tok::r_brace:
case tok::comma:
case tok::colon:
prevTok = currTok;
return false;
}
prevTok = currTok;
return true;
}
static std::string PatchMSAsmString(Sema &SemaRef, bool &IsSimple,
SourceLocation AsmLoc,
ArrayRef<Token> AsmToks,
const TargetInfo &TI) {
std::string Res;
IdentifierInfo *II = AsmToks[0].getIdentifierInfo();
Res = II->getName().str();
// Assume simple asm stmt until we parse a non-register identifer.
IsSimple = true;
// Check the operands.
for (unsigned i = 1, e = AsmToks.size(); i != e; ++i) {
if (needSpaceAsmToken(AsmToks[i]))
Res += " ";
switch (AsmToks[i].getKind()) {
default:
//llvm_unreachable("Unknown token.");
break;
case tok::comma: Res += ","; break;
case tok::colon: Res += ":"; break;
case tok::l_square: Res += "["; break;
case tok::r_square: Res += "]"; break;
case tok::l_brace: Res += "{"; break;
case tok::r_brace: Res += "}"; break;
case tok::numeric_constant: {
SmallString<32> TokenBuf;
TokenBuf.resize(32);
bool StringInvalid = false;
const char *ThisTokBuf = &TokenBuf[0];
unsigned ThisTokLen =
Lexer::getSpelling(AsmToks[i], ThisTokBuf, SemaRef.getSourceManager(),
SemaRef.getLangOpts(), &StringInvalid);
Res += StringRef(ThisTokBuf, ThisTokLen);
break;
}
case tok::identifier: {
II = AsmToks[i].getIdentifierInfo();
StringRef Name = II->getName();
// Valid registers don't need modification.
if (TI.isValidGCCRegisterName(Name)) {
Res += Name;
break;
}
// TODO: Lookup the identifier.
IsSimple = false;
}
} // AsmToks[i].getKind()
}
return Res;
}
StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc,
ArrayRef<Token> AsmToks,
std::string &AsmString,
@ -2754,9 +2847,18 @@ StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc,
// MS-style inline assembly is not fully supported, so emit a warning.
Diag(AsmLoc, diag::warn_unsupported_msasm);
bool IsSimple;
// Rewrite operands to appease the AsmParser.
std::string PatchedAsmString =
PatchMSAsmString(*this, IsSimple, AsmLoc, AsmToks, Context.getTargetInfo());
// Silence compiler warnings. Eventually, the PatchedAsmString will be
// passed to the AsmParser.
(void)PatchedAsmString;
MSAsmStmt *NS =
new (Context) MSAsmStmt(Context, AsmLoc, true, true, AsmToks, AsmString,
EndLoc);
new (Context) MSAsmStmt(Context, AsmLoc, IsSimple, /* IsVolatile */ true,
AsmToks, AsmString, EndLoc);
return Owned(NS);
}