From f37e4218bb40ed956f0ef1d2e5eee2b2c3aa20d2 Mon Sep 17 00:00:00 2001 From: Chad Rosier Date: Wed, 15 Aug 2012 21:03:27 +0000 Subject: [PATCH] [ms-inline asm] MSVC parses multiple __asm statements on a single line as one statement. For example, if (x) __asm out dx, ax __asm out dx, ax results in a single inline asm statement (i.e., both "out dx, ax" statements are predicated on if(x)). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@161986 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Parse/ParseStmt.cpp | 5 ----- lib/Sema/SemaStmt.cpp | 37 ++++++++++++++++++++++++++++-------- test/CodeGen/ms-inline-asm.c | 7 ++----- test/Parser/ms-inline-asm.c | 4 ++-- 4 files changed, 33 insertions(+), 20 deletions(-) diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index 0af1d08298..a934847c01 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -1686,11 +1686,6 @@ StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) { if (Tok.is(tok::eof)) break; - // The asm keyword is a statement separator, so multiple asm statements - // are allowed on a single line. - if (!InAsmComment && Tok.is(tok::kw_asm)) - break; - if (!InAsmComment && Tok.is(tok::semi)) { // A semicolon in an asm is the start of a comment. InAsmComment = true; diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 3d58a5d57f..2aabd9ee79 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -2777,12 +2777,21 @@ static void patchMSAsmStrings(Sema &SemaRef, bool &IsSimple, unsigned NumAsmStrings = 0; for (unsigned i = 0, e = AsmToks.size(); i != e; ++i) { + // Determine if this should be considered a new asm. + bool isNewAsm = i == 0 || AsmToks[i].isAtStartOfLine() || + AsmToks[i].is(tok::kw_asm); + // Emit the previous asm string. - if (i && AsmToks[i].isAtStartOfLine()) + if (i && isNewAsm) { AsmStrings[NumAsmStrings++] = Asm.c_str(); + if (AsmToks[i].is(tok::kw_asm)) { + ++i; // Skip __asm + assert (i != e && "Expected another token."); + } + } // Start a new asm string with the opcode. - if (i == 0 || AsmToks[i].isAtStartOfLine()) { + if (isNewAsm) { Asm = AsmToks[i].getIdentifierInfo()->getName().str(); continue; } @@ -2831,17 +2840,29 @@ static void patchMSAsmStrings(Sema &SemaRef, bool &IsSimple, // Build the unmodified MSAsmString. static std::string buildMSAsmString(Sema &SemaRef, - ArrayRef AsmToks) { + ArrayRef AsmToks) { assert (!AsmToks.empty() && "Didn't expect an empty AsmToks!"); SmallString<512> Asm; SmallString<512> TokenBuf; TokenBuf.resize(512); + for (unsigned i = 0, e = AsmToks.size(); i < e; ++i) { - bool StringInvalid = false; - if (i && AsmToks[i].isAtStartOfLine()) - Asm += '\n'; - else if (i && AsmToks[i].hasLeadingSpace()) + bool isNewAsm = i == 0 || AsmToks[i].isAtStartOfLine() || + AsmToks[i].is(tok::kw_asm); + + if (isNewAsm) { + if (i) + Asm += '\n'; + if (AsmToks[i].is(tok::kw_asm)) { + i++; // Skip __asm + assert (i != e && "Expected another token"); + } + } + + if (i && AsmToks[i].hasLeadingSpace() && !isNewAsm) Asm += ' '; + + bool StringInvalid = false; Asm += SemaRef.PP.getSpelling(AsmToks[i], TokenBuf, &StringInvalid); assert (!StringInvalid && "Expected valid string!"); } @@ -2876,7 +2897,7 @@ StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc, // FIXME: Count this while parsing. unsigned NumAsmStrings = 0; for (unsigned i = 0, e = AsmToks.size(); i != e; ++i) - if (AsmToks[i].isAtStartOfLine()) + if (i == 0 || AsmToks[i].isAtStartOfLine() || AsmToks[i].is(tok::kw_asm)) ++NumAsmStrings; PatchedAsmStrings.resize(NumAsmStrings ? NumAsmStrings : 1); diff --git a/test/CodeGen/ms-inline-asm.c b/test/CodeGen/ms-inline-asm.c index fe0d3a5826..f54c226e60 100644 --- a/test/CodeGen/ms-inline-asm.c +++ b/test/CodeGen/ms-inline-asm.c @@ -20,9 +20,7 @@ void t2() { void t3() { // CHECK: @t3 -// CHECK: call void asm sideeffect "nop", "~{dirflag},~{fpsr},~{flags}"() nounwind ia_nsdialect -// CHECK: call void asm sideeffect "nop", "~{dirflag},~{fpsr},~{flags}"() nounwind ia_nsdialect -// CHECK: call void asm sideeffect "nop", "~{dirflag},~{fpsr},~{flags}"() nounwind ia_nsdialect +// CHECK: call void asm sideeffect "nop\0Anop\0Anop", "~{dirflag},~{fpsr},~{flags}"() nounwind ia_nsdialect // CHECK: ret void __asm nop __asm nop __asm nop } @@ -38,8 +36,7 @@ void t4(void) { void t5(void) { // CHECK: @t5 -// CHECK: call void asm sideeffect "mov ebx, eax", "~{ebx},~{dirflag},~{fpsr},~{flags}"() nounwind ia_nsdialect -// CHECK: call void asm sideeffect "mov ecx, ebx", "~{ecx},~{dirflag},~{fpsr},~{flags}"() nounwind ia_nsdialect +// CHECK: call void asm sideeffect "mov ebx, eax\0Amov ecx, ebx", "~{ebx},~{ecx},~{dirflag},~{fpsr},~{flags}"() nounwind ia_nsdialect // CHECK: ret void __asm mov ebx, eax __asm mov ecx, ebx } diff --git a/test/Parser/ms-inline-asm.c b/test/Parser/ms-inline-asm.c index 6820f3e642..5326ce4d24 100644 --- a/test/Parser/ms-inline-asm.c +++ b/test/Parser/ms-inline-asm.c @@ -28,10 +28,10 @@ int t7() { } } void t8() { - __asm nop __asm nop __asm nop // expected-warning {{MS-style inline assembly is not supported}} expected-warning {{MS-style inline assembly is not supported}} expected-warning {{MS-style inline assembly is not supported}} + __asm nop __asm nop __asm nop // expected-warning {{MS-style inline assembly is not supported}} } void t9() { - __asm nop __asm nop ; __asm nop // expected-warning {{MS-style inline assembly is not supported}} expected-warning {{MS-style inline assembly is not supported}} + __asm nop __asm nop ; __asm nop // expected-warning {{MS-style inline assembly is not supported}} } int t_fail() { // expected-note {{to match this}} __asm -- 2.40.0