forked from OSchip/llvm-project
[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:
parent
e71b6c6b20
commit
d12b7a64dc
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue