From d12b7a64dc4351f185da554551b640a9d0594078 Mon Sep 17 00:00:00 2001 From: Chad Rosier Date: Wed, 8 Aug 2012 18:22:06 +0000 Subject: [PATCH] [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 --- clang/lib/Sema/SemaStmt.cpp | 106 +++++++++++++++++++++++++++++++++++- 1 file changed, 104 insertions(+), 2 deletions(-) diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 2161aebe38e3..80f58b90c36a 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/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 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 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); }