diff options
author | Chad Rosier <mcrosier@apple.com> | 2012-08-08 18:22:06 +0000 |
---|---|---|
committer | Chad Rosier <mcrosier@apple.com> | 2012-08-08 18:22:06 +0000 |
commit | e696b6924d14b0e0590b5d923ca1646e6f67ac40 (patch) | |
tree | e383b738378b0557f73580418c7e3e102264c488 /lib/Sema/SemaStmt.cpp | |
parent | 3a32c9c565f970fd319b97a6056a4725cfa4f0f5 (diff) |
[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.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@161508 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaStmt.cpp')
-rw-r--r-- | lib/Sema/SemaStmt.cpp | 106 |
1 files changed, 104 insertions, 2 deletions
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 2161aebe38..80f58b90c3 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -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); } |