diff options
author | Chad Rosier <mcrosier@apple.com> | 2012-08-13 20:32:07 +0000 |
---|---|---|
committer | Chad Rosier <mcrosier@apple.com> | 2012-08-13 20:32:07 +0000 |
commit | 265f538b2c8b9e19196ce8a78a3da78671eb6f2b (patch) | |
tree | e55a0e00755c9ed0140287947874661d87d74b35 /lib/Sema/SemaStmt.cpp | |
parent | 0d729105ecb50a7e3cbe6e57c29149edfa5cf05a (diff) |
[ms-inline asm] Have patchMSAsmStrings() return a vector or AsmStrings.
The AsmParser expects a single asm instruction, but valid ms-style inline asm
statements may contain multiple instructions.
This happens with asm blocks
__asm {
mov ebx, eax
mov ecx, ebx
}
or when multiple asm statements are adjacent to one another
__asm mov ebx, eax
__asm mov ecx, ebx
and
__asm mov ebx, eax __asm mov ecx, ebx
Currently, asm blocks are not properly handled.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@161780 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaStmt.cpp')
-rw-r--r-- | lib/Sema/SemaStmt.cpp | 141 |
1 files changed, 79 insertions, 62 deletions
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 347b34f78a..2a7ca99a6a 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -2794,60 +2794,71 @@ static inline bool needSpaceAsmToken(Token currTok) { return true; } -static std::string PatchMSAsmString(Sema &SemaRef, bool &IsSimple, - SourceLocation AsmLoc, - ArrayRef<Token> AsmToks, - const TargetInfo &TI) { +static void patchMSAsmStrings(Sema &SemaRef, bool &IsSimple, + SourceLocation AsmLoc, + ArrayRef<Token> AsmToks, + ArrayRef<unsigned> LineEnds, + const TargetInfo &TI, + std::vector<std::string> &AsmStrings) { assert (!AsmToks.empty() && "Didn't expect an empty AsmToks!"); - 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(); + for (unsigned i = 0, e = LineEnds.size(); i != e; ++i) { + SmallString<512> Asm; + + // Check the operands. + for (unsigned j = (i == 0) ? 0 : LineEnds[i-1], e = LineEnds[i]; j != e; ++j) { + + IdentifierInfo *II; + if (j == 0 || (i > 0 && j == LineEnds[i-1])) { + II = AsmToks[j].getIdentifierInfo(); + Asm = II->getName().str(); + continue; + } - // Valid registers don't need modification. - if (TI.isValidGCCRegisterName(Name)) { - Res += Name; + if (needSpaceAsmToken(AsmToks[j])) + Asm += " "; + + switch (AsmToks[j].getKind()) { + default: + //llvm_unreachable("Unknown token."); + break; + case tok::comma: Asm += ","; break; + case tok::colon: Asm += ":"; break; + case tok::l_square: Asm += "["; break; + case tok::r_square: Asm += "]"; break; + case tok::l_brace: Asm += "{"; break; + case tok::r_brace: Asm += "}"; break; + case tok::numeric_constant: { + SmallString<32> TokenBuf; + TokenBuf.resize(32); + bool StringInvalid = false; + const char *ThisTokBuf = &TokenBuf[0]; + unsigned ThisTokLen = + Lexer::getSpelling(AsmToks[j], ThisTokBuf, SemaRef.getSourceManager(), + SemaRef.getLangOpts(), &StringInvalid); + Asm += StringRef(ThisTokBuf, ThisTokLen); break; } + case tok::identifier: { + II = AsmToks[j].getIdentifierInfo(); + StringRef Name = II->getName(); - // TODO: Lookup the identifier. - IsSimple = false; + // Valid registers don't need modification. + if (TI.isValidGCCRegisterName(Name)) { + Asm += Name; + break; + } + + // TODO: Lookup the identifier. + IsSimple = false; + } + } // AsmToks[i].getKind() } - } // AsmToks[i].getKind() + AsmStrings[i] = Asm.c_str(); } - return Res; } // Build the unmodified MSAsmString. @@ -2898,11 +2909,14 @@ StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc, std::string AsmString = buildMSAsmString(*this, AsmToks, LineEnds); bool IsSimple; + std::vector<std::string> PatchedAsmStrings; + PatchedAsmStrings.resize(LineEnds.size()); + // Rewrite operands to appease the AsmParser. - std::string PatchedAsmString = - PatchMSAsmString(*this, IsSimple, AsmLoc, AsmToks, Context.getTargetInfo()); + patchMSAsmStrings(*this, IsSimple, AsmLoc, AsmToks, LineEnds, + Context.getTargetInfo(), PatchedAsmStrings); - // PatchMSAsmString doesn't correctly patch non-simple asm statements. + // patchMSAsmStrings doesn't correctly patch non-simple asm statements. if (!IsSimple) { MSAsmStmt *NS = new (Context) MSAsmStmt(Context, AsmLoc, /* IsSimple */ true, @@ -2921,29 +2935,32 @@ StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc, const std::string &TT = Context.getTargetInfo().getTriple().getTriple(); const llvm::Target *TheTarget(llvm::TargetRegistry::lookupTarget(TT, Error)); - llvm::SourceMgr SrcMgr; - llvm::MemoryBuffer *Buffer = - llvm::MemoryBuffer::getMemBuffer(PatchedAsmString, "<inline asm>"); - - // Tell SrcMgr about this buffer, which is what the parser will pick up. - SrcMgr.AddNewSourceBuffer(Buffer, llvm::SMLoc()); - OwningPtr<llvm::MCAsmInfo> MAI(TheTarget->createMCAsmInfo(TT)); OwningPtr<llvm::MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TT)); OwningPtr<llvm::MCObjectFileInfo> MOFI(new llvm::MCObjectFileInfo()); - llvm::MCContext Ctx(*MAI, *MRI, MOFI.get(), &SrcMgr); OwningPtr<llvm::MCSubtargetInfo> STI(TheTarget->createMCSubtargetInfo(TT, "", "")); - OwningPtr<llvm::MCStreamer> Str; - OwningPtr<llvm::MCAsmParser> - Parser(createMCAsmParser(SrcMgr, Ctx, *Str.get(), *MAI)); - OwningPtr<llvm::MCTargetAsmParser> - TargetParser(TheTarget->createMCAsmParser(*STI, *Parser)); + for (unsigned i = 0, e = PatchedAsmStrings.size(); i != e; ++i) { + llvm::SourceMgr SrcMgr; + llvm::MCContext Ctx(*MAI, *MRI, MOFI.get(), &SrcMgr); + llvm::MemoryBuffer *Buffer = + llvm::MemoryBuffer::getMemBuffer(PatchedAsmStrings[i], "<inline asm>"); + + // Tell SrcMgr about this buffer, which is what the parser will pick up. + SrcMgr.AddNewSourceBuffer(Buffer, llvm::SMLoc()); - // Change to the Intel dialect. - Parser->setAssemblerDialect(1); - Parser->setTargetParser(*TargetParser.get()); + OwningPtr<llvm::MCStreamer> Str; + OwningPtr<llvm::MCAsmParser> + Parser(createMCAsmParser(SrcMgr, Ctx, *Str.get(), *MAI)); + OwningPtr<llvm::MCTargetAsmParser> + TargetParser(TheTarget->createMCAsmParser(*STI, *Parser)); + // Change to the Intel dialect. + Parser->setAssemblerDialect(1); + Parser->setTargetParser(*TargetParser.get()); + + // TODO: Start parsing. + } MSAsmStmt *NS = new (Context) MSAsmStmt(Context, AsmLoc, IsSimple, /* IsVolatile */ true, |