[cfe-commits] r161780 - in /cfe/trunk: lib/Sema/SemaStmt.cpp test/CodeGen/ms-inline-asm.c
Chad Rosier
mcrosier at apple.com
Mon Aug 13 13:32:07 PDT 2012
Author: mcrosier
Date: Mon Aug 13 15:32:07 2012
New Revision: 161780
URL: http://llvm.org/viewvc/llvm-project?rev=161780&view=rev
Log:
[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.
Modified:
cfe/trunk/lib/Sema/SemaStmt.cpp
cfe/trunk/test/CodeGen/ms-inline-asm.c
Modified: cfe/trunk/lib/Sema/SemaStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=161780&r1=161779&r2=161780&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaStmt.cpp (original)
+++ cfe/trunk/lib/Sema/SemaStmt.cpp Mon Aug 13 15:32:07 2012
@@ -2794,60 +2794,71 @@
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();
-
- // Valid registers don't need modification.
- if (TI.isValidGCCRegisterName(Name)) {
- Res += Name;
+ 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;
+ }
+
+ 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();
+
+ // Valid registers don't need modification.
+ if (TI.isValidGCCRegisterName(Name)) {
+ Asm += Name;
+ break;
+ }
- // TODO: Lookup the identifier.
- IsSimple = false;
+ // 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 @@
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 @@
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));
-
- // Change to the Intel dialect.
- Parser->setAssemblerDialect(1);
- Parser->setTargetParser(*TargetParser.get());
+ 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());
+
+ 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,
Modified: cfe/trunk/test/CodeGen/ms-inline-asm.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/ms-inline-asm.c?rev=161780&r1=161779&r2=161780&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/ms-inline-asm.c (original)
+++ cfe/trunk/test/CodeGen/ms-inline-asm.c Mon Aug 13 15:32:07 2012
@@ -6,3 +6,35 @@
// CHECK: ret void
__asm {}
}
+
+void t2() {
+// CHECK: @t2
+// CHECK: call void asm sideeffect "nop\0Anop\0Anop", "~{dirflag},~{fpsr},~{flags}"() nounwind ia_nsdialect
+// CHECK: ret void
+ __asm nop
+ __asm nop
+ __asm nop
+}
+
+void t3() {
+// CHECK: @t3
+// CHECK: call void asm sideeffect "nop\0Anop\0Anop", "~{dirflag},~{fpsr},~{flags}"() nounwind ia_nsdialect
+// CHECK: ret void
+ __asm nop __asm nop __asm nop
+}
+
+void t4(void) {
+// CHECK: @t4
+// CHECK: call void asm sideeffect "mov ebx, eax\0Amov ecx, ebx", "~{dirflag},~{fpsr},~{flags}"() nounwind ia_nsdialect
+// CHECK: ret void
+ __asm mov ebx, eax
+ __asm mov ecx, ebx
+}
+
+void t5(void) {
+// CHECK: @t5
+// CHECK: call void asm sideeffect "mov ebx, eax\0Amov ecx, ebx", "~{dirflag},~{fpsr},~{flags}"() nounwind ia_nsdialect
+// CHECK: ret void
+ __asm mov ebx, eax __asm mov ecx, ebx
+}
+
More information about the cfe-commits
mailing list