Addressed the review comment.

http://reviews.llvm.org/D4589

Files:
  include/clang/AST/Decl.h
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Sema/Sema.h
  lib/AST/Decl.cpp
  lib/Parse/ParseStmtAsm.cpp
  lib/Sema/JumpDiagnostics.cpp
  lib/Sema/Sema.cpp
  lib/Sema/SemaDecl.cpp
  lib/Sema/SemaStmt.cpp
  lib/Sema/SemaStmtAsm.cpp
  test/CodeGen/mozilla-ms-inline-asm.c
  test/CodeGen/ms-inline-asm.c
  test/CodeGen/ms-inline-asm.cpp
  test/Parser/ms-inline-asm.c
  test/Sema/ms-inline-asm.c
Index: include/clang/AST/Decl.h
===================================================================
--- include/clang/AST/Decl.h
+++ include/clang/AST/Decl.h
@@ -308,14 +308,19 @@
 class LabelDecl : public NamedDecl {
   void anchor() override;
   LabelStmt *TheStmt;
+  StringRef MSAsmName;
+  bool MSAsmNameResolved;
   /// LocStart - For normal labels, this is the same as the main declaration
   /// label, i.e., the location of the identifier; for GNU local labels,
   /// this is the location of the __label__ keyword.
   SourceLocation LocStart;
 
   LabelDecl(DeclContext *DC, SourceLocation IdentL, IdentifierInfo *II,
             LabelStmt *S, SourceLocation StartL)
-    : NamedDecl(Label, DC, IdentL, II), TheStmt(S), LocStart(StartL) {}
+    : NamedDecl(Label, DC, IdentL, II),
+      TheStmt(S),
+      MSAsmNameResolved(false),
+      LocStart(StartL) {}
 
 public:
   static LabelDecl *Create(ASTContext &C, DeclContext *DC,
@@ -335,6 +340,12 @@
     return SourceRange(LocStart, getLocation());
   }
 
+  bool isMSAsmLabel() const { return MSAsmName.size() != 0; }
+  bool isResolvedMSAsmLabel() const { return isMSAsmLabel() && MSAsmNameResolved; }
+  void setMSAsmLabel(StringRef Name);
+  StringRef getMSAsmLabel() const { return MSAsmName; }
+  void setMSAsmLabelResolved() { MSAsmNameResolved = true; }
+
   // Implement isa/cast/dyncast/etc.
   static bool classof(const Decl *D) { return classofKind(D->getKind()); }
   static bool classofKind(Kind K) { return K == Label; }
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -4116,6 +4116,10 @@
 
 def err_redefinition_of_label : Error<"redefinition of label %0">;
 def err_undeclared_label_use : Error<"use of undeclared label %0">;
+def err_goto_ms_asm_label : Error<
+  "cannot jump from this goto statement to label %0 inside an inline assembly block">;
+def note_goto_ms_asm_label : Note<
+  "inline assembly label %0 declared here">;
 def warn_unused_label : Warning<"unused label %0">,
   InGroup<UnusedLabel>, DefaultIgnore;
 
Index: include/clang/Sema/Sema.h
===================================================================
--- include/clang/Sema/Sema.h
+++ include/clang/Sema/Sema.h
@@ -699,7 +699,10 @@
 
   /// \brief will hold 'respondsToSelector:'
   Selector RespondsToSelectorSel;
-  
+
+  /// \brief counter for internal MS Asm label names.
+  unsigned MSAsmLabelNameCounter;
+
   /// A flag to remember whether the implicit forms of operator new and delete
   /// have been declared.
   bool GlobalNewDeleteDeclared;
@@ -3156,6 +3159,9 @@
                             ArrayRef<StringRef> Clobbers,
                             ArrayRef<Expr*> Exprs,
                             SourceLocation EndLoc);
+  LabelDecl *GetOrCreateMSAsmLabel(StringRef ExternalLabelName,
+                                   SourceLocation Location,
+                                   bool AlwaysCreate);
 
   VarDecl *BuildObjCExceptionDecl(TypeSourceInfo *TInfo, QualType ExceptionType,
                                   SourceLocation StartLoc,
Index: lib/AST/Decl.cpp
===================================================================
--- lib/AST/Decl.cpp
+++ lib/AST/Decl.cpp
@@ -3709,6 +3709,13 @@
                                SourceLocation());
 }
 
+void LabelDecl::setMSAsmLabel(StringRef Name) {
+  char *Buffer = new (getASTContext(), 1) char[Name.size() + 1];
+  memcpy(Buffer, Name.data(), Name.size());
+  Buffer[Name.size()] = '\0';
+  MSAsmName = Buffer;
+}
+
 void ValueDecl::anchor() { }
 
 bool ValueDecl::isWeak() const {
Index: lib/Parse/ParseStmtAsm.cpp
===================================================================
--- lib/Parse/ParseStmtAsm.cpp
+++ lib/Parse/ParseStmtAsm.cpp
@@ -93,6 +93,15 @@
     return Info.OpDecl;
   }
 
+  StringRef LookupInlineAsmLabel(StringRef Identifier, llvm::SourceMgr &LSM,
+                                 llvm::SMLoc Location,
+                                 bool Create) override {
+    SourceLocation Loc = translateLocation(LSM, Location);
+    LabelDecl *Label =
+      TheParser.getActions().GetOrCreateMSAsmLabel(Identifier, Loc, Create);
+    return Label->getMSAsmLabel();
+  }
+
   bool LookupInlineAsmField(StringRef Base, StringRef Member,
                             unsigned &Offset) override {
     return TheParser.getActions().LookupInlineAsmField(Base, Member, Offset,
@@ -133,14 +142,13 @@
     }
   }
 
-  void handleDiagnostic(const llvm::SMDiagnostic &D) {
+  SourceLocation translateLocation(const llvm::SourceMgr &LSM, llvm::SMLoc SMLoc) {
     // Compute an offset into the inline asm buffer.
     // FIXME: This isn't right if .macro is involved (but hopefully, no
     // real-world code does that).
-    const llvm::SourceMgr &LSM = *D.getSourceMgr();
     const llvm::MemoryBuffer *LBuf =
-        LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(D.getLoc()));
-    unsigned Offset = D.getLoc().getPointer() - LBuf->getBufferStart();
+        LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(SMLoc));
+    unsigned Offset = SMLoc.getPointer() - LBuf->getBufferStart();
 
     // Figure out which token that offset points into.
     const unsigned *TokOffsetPtr =
@@ -157,6 +165,12 @@
       Loc = Tok.getLocation();
       Loc = Loc.getLocWithOffset(Offset - TokOffset);
     }
+    return Loc;
+  }
+
+  void handleDiagnostic(const llvm::SMDiagnostic &D) {
+    const llvm::SourceMgr &LSM = *D.getSourceMgr();
+    SourceLocation Loc = translateLocation(LSM, D.getLoc());
     TheParser.Diag(Loc, diag::err_inline_ms_asm_parsing) << D.getMessage();
   }
 };
Index: lib/Sema/JumpDiagnostics.cpp
===================================================================
--- lib/Sema/JumpDiagnostics.cpp
+++ lib/Sema/JumpDiagnostics.cpp
@@ -84,6 +84,7 @@
   void CheckJump(Stmt *From, Stmt *To, SourceLocation DiagLoc,
                  unsigned JumpDiag, unsigned JumpDiagWarning,
                  unsigned JumpDiagCXX98Compat);
+  void CheckGotoStmt(GotoStmt *GS);
 
   unsigned GetDeepestCommonScope(unsigned A, unsigned B);
 };
@@ -489,10 +490,14 @@
 
     // With a goto,
     if (GotoStmt *GS = dyn_cast<GotoStmt>(Jump)) {
-      CheckJump(GS, GS->getLabel()->getStmt(), GS->getGotoLoc(),
-                diag::err_goto_into_protected_scope,
-                diag::ext_goto_into_protected_scope,
-                diag::warn_cxx98_compat_goto_into_protected_scope);
+      // The label may not have a statement if it's coming from inline MS ASM.
+      if (GS->getLabel()->getStmt()) {
+        CheckJump(GS, GS->getLabel()->getStmt(), GS->getGotoLoc(),
+                  diag::err_goto_into_protected_scope,
+                  diag::ext_goto_into_protected_scope,
+                  diag::warn_cxx98_compat_goto_into_protected_scope);
+      }
+      CheckGotoStmt(GS);
       continue;
     }
 
@@ -789,6 +794,15 @@
   }
 }
 
+void JumpScopeChecker::CheckGotoStmt(GotoStmt *GS) {
+  if (GS->getLabel()->isMSAsmLabel()) {
+    S.Diag(GS->getGotoLoc(), diag::err_goto_ms_asm_label)
+        << GS->getLabel()->getIdentifier();
+    S.Diag(GS->getLabel()->getLocation(), diag::note_goto_ms_asm_label)
+        << GS->getLabel()->getIdentifier();
+  }
+}
+
 void Sema::DiagnoseInvalidJumps(Stmt *Body) {
   (void)JumpScopeChecker(Body, *this);
 }
Index: lib/Sema/Sema.cpp
===================================================================
--- lib/Sema/Sema.cpp
+++ lib/Sema/Sema.cpp
@@ -98,6 +98,7 @@
     InitDictionaryWithObjectsMethod(nullptr),
     ArrayAllocObjectsMethod(nullptr),
     DictAllocObjectsMethod(nullptr),
+    MSAsmLabelNameCounter(0),
     GlobalNewDeleteDeclared(false),
     TUKind(TUKind),
     NumSFINAEErrors(0),
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -1517,8 +1517,14 @@
 static void CheckPoppedLabel(LabelDecl *L, Sema &S) {
   // Verify that we have no forward references left.  If so, there was a goto
   // or address of a label taken, but no definition of it.  Label fwd
-  // definitions are indicated with a null substmt.
-  if (L->getStmt() == nullptr)
+  // definitions are indicated with a null substmt which is also not a resolved
+  // MS inline assembly label name.
+  bool Diagnose = false;
+  if (L->isMSAsmLabel())
+    Diagnose = !L->isResolvedMSAsmLabel();
+  else
+    Diagnose = L->getStmt() == nullptr;
+  if (Diagnose)
     S.Diag(L->getLocation(), diag::err_undeclared_label_use) <<L->getDeclName();
 }
 
Index: lib/Sema/SemaStmt.cpp
===================================================================
--- lib/Sema/SemaStmt.cpp
+++ lib/Sema/SemaStmt.cpp
@@ -432,7 +432,11 @@
   TheDecl->setStmt(LS);
   if (!TheDecl->isGnuLocal()) {
     TheDecl->setLocStart(IdentLoc);
-    TheDecl->setLocation(IdentLoc);
+    if (!TheDecl->isMSAsmLabel()) {
+      // Don't update the location of MS ASM labels.  These will result in
+      // a diagnostic, and changing the location here will mess that up.
+      TheDecl->setLocation(IdentLoc);
+    }
   }
   return LS;
 }
Index: lib/Sema/SemaStmtAsm.cpp
===================================================================
--- lib/Sema/SemaStmtAsm.cpp
+++ lib/Sema/SemaStmtAsm.cpp
@@ -15,6 +15,7 @@
 #include "clang/AST/RecordLayout.h"
 #include "clang/AST/TypeLoc.h"
 #include "clang/Basic/TargetInfo.h"
+#include "clang/Lex/Preprocessor.h"
 #include "clang/Sema/Initialization.h"
 #include "clang/Sema/Lookup.h"
 #include "clang/Sema/Scope.h"
@@ -506,10 +507,39 @@
                                 ArrayRef<Expr*> Exprs,
                                 SourceLocation EndLoc) {
   bool IsSimple = (NumOutputs != 0 || NumInputs != 0);
+  getCurFunction()->setHasBranchProtectedScope();
   MSAsmStmt *NS =
     new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, IsSimple,
                             /*IsVolatile*/ true, AsmToks, NumOutputs, NumInputs,
                             Constraints, Exprs, AsmString,
                             Clobbers, EndLoc);
   return NS;
 }
+
+LabelDecl *Sema::GetOrCreateMSAsmLabel(StringRef ExternalLabelName,
+                                       SourceLocation Location,
+                                       bool AlwaysCreate) {
+  LabelDecl* Label = LookupOrCreateLabel(PP.getIdentifierInfo(ExternalLabelName),
+                                         Location);
+
+  if (!Label->isMSAsmLabel()) {
+    // Otherwise, insert it, but only resolve it if we have seen the label itself.
+    std::string InternalName;
+    llvm::raw_string_ostream OS(InternalName);
+    // Create an internal name for the label.  The name should not be a valid mangled
+    // name, and should be unique.  We use a dot to make the name an invalid mangled
+    // name.
+    OS << "__MSASMLABEL_." << MSAsmLabelNameCounter++ << "__" << ExternalLabelName;
+    Label->setMSAsmLabel(OS.str());
+  }
+  if (AlwaysCreate) {
+    // The label might have been created implicitly from a previously encountered
+    // goto statement.  So, for both newly created and looked up labels, we mark
+    // them as resolved.
+    Label->setMSAsmLabelResolved();
+  }
+  // Adjust their location for being able to generate accurate diagnostics.
+  Label->setLocation(Location);
+
+  return Label;
+}
Index: test/CodeGen/mozilla-ms-inline-asm.c
===================================================================
--- test/CodeGen/mozilla-ms-inline-asm.c
+++ test/CodeGen/mozilla-ms-inline-asm.c
@@ -3,6 +3,8 @@
 
 // Some test cases for MS inline asm support from Mozilla code base.
 
+void invoke_copy_to_stack() {}
+
 void invoke(void* that, unsigned methodIndex,
             unsigned paramCount, void* params)
 {
@@ -18,24 +20,25 @@
 // CHECK: call void asm sideeffect inteldialect
 // CHECK: mov edx,dword ptr $1
 // CHECK: test edx,edx
-// CHECK: jz noparams
+// CHECK: jz {{[^_]*}}__MSASMLABEL_.0__noparams
+//             ^ Can't use {{.*}} here because the matching is greedy.
 // CHECK: mov eax,edx
 // CHECK: shl eax,$$3
 // CHECK: sub esp,eax
 // CHECK: mov ecx,esp
 // CHECK: push dword ptr $0
-// CHECK: call invoke_copy_to_stack
-// CHECK: noparams:
-// CHECK: mov ecx,dword ptr $2
+// CHECK: call dword ptr $2
+// CHECK: {{.*}}__MSASMLABEL_.0__noparams:
+// CHECK: mov ecx,dword ptr $3
 // CHECK: push ecx
 // CHECK: mov edx,[ecx]
-// CHECK: mov eax,dword ptr $3
+// CHECK: mov eax,dword ptr $4
 // CHECK: call dword ptr[edx+eax*$$4]
 // CHECK: mov esp,ebp
 // CHECK: pop ebp
 // CHECK: ret
-// CHECK: "=*m,*m,*m,*m,~{eax},~{ebp},~{ecx},~{edx},~{flags},~{esp},~{dirflag},~{fpsr},~{flags}"
-// CHECK: (i8** %8, i32* %7, i8** %5, i32* %6)
+// CHECK: "=*m,*m,*m,*m,*m,~{eax},~{ebp},~{ecx},~{edx},~{flags},~{esp},~{dirflag},~{fpsr},~{flags}"
+// CHECK: (i8** %8, i32* %7, void (...)* bitcast (void ()* @invoke_copy_to_stack to void (...)*), i8** %5, i32* %6)
 // CHECK: ret void
     __asm {
         mov     edx,paramCount
Index: test/CodeGen/ms-inline-asm.c
===================================================================
--- test/CodeGen/ms-inline-asm.c
+++ test/CodeGen/ms-inline-asm.c
@@ -240,7 +240,7 @@
   the_label:
   }
 // CHECK: t23
-// CHECK: call void asm sideeffect inteldialect "the_label:", "~{dirflag},~{fpsr},~{flags}"()
+// CHECK: call void asm sideeffect inteldialect "{{.*}}__MSASMLABEL_.0__the_label:", "~{dirflag},~{fpsr},~{flags}"()
 }
 
 void t24_helper(void) {}
@@ -517,3 +517,30 @@
 }
 // CHECK-LABEL: define void @xgetbv()
 // CHECK: call void asm sideeffect inteldialect "xgetbv", "~{eax},~{edx},~{dirflag},~{fpsr},~{flags}"()
+
+void label1() {
+  __asm {
+    label:
+    jmp label
+  }
+  // CHECK-LABEL: define void @label1
+  // CHECK: call void asm sideeffect inteldialect "{{.*}}__MSASMLABEL_.1__label:\0A\09jmp {{.*}}__MSASMLABEL_.1__label", "~{dirflag},~{fpsr},~{flags}"()
+}
+
+void label2() {
+  __asm {
+    jmp label
+    label:
+  }
+  // CHECK-LABEL: define void @label2
+  // CHECK: call void asm sideeffect inteldialect "jmp {{.*}}__MSASMLABEL_.2__label\0A\09{{.*}}__MSASMLABEL_.2__label:", "~{dirflag},~{fpsr},~{flags}"()
+}
+
+void label3() {
+  __asm {
+    label:
+    mov eax, label
+  }
+  // CHECK-LABEL: define void @label3
+  // CHECK: call void asm sideeffect inteldialect "{{.*}}__MSASMLABEL_.3__label:\0A\09mov eax, {{.*}}__MSASMLABEL_.3__label", "~{eax},~{dirflag},~{fpsr},~{flags}"()
+}
Index: test/CodeGen/ms-inline-asm.cpp
===================================================================
--- test/CodeGen/ms-inline-asm.cpp
+++ test/CodeGen/ms-inline-asm.cpp
@@ -122,3 +122,20 @@
   // CHECK-LABEL: define void @_Z8t7_usingv
   // CHECK: call void asm sideeffect inteldialect "mov eax, [eax].4", "~{eax},~{dirflag},~{fpsr},~{flags}"()
 }
+
+void t8() {
+  __asm some_label:
+  // CHECK-LABEL: define void @_Z2t8v()
+  // CHECK: call void asm sideeffect inteldialect "L__MSASMLABEL_.1__some_label:", "~{dirflag},~{fpsr},~{flags}"()
+  struct A {
+    static void g() {
+      __asm jmp some_label ; This should jump forwards
+      __asm some_label:
+      __asm nop
+      // CHECK-LABEL: define internal void @_ZZ2t8vEN1A1gEv()
+      // CHECK: call void asm sideeffect inteldialect "jmp L__MSASMLABEL_.2__some_label\0A\09L__MSASMLABEL_.2__some_label:\0A\09nop", "~{dirflag},~{fpsr},~{flags}"()
+    }
+  };
+  A::g();
+}
+
Index: test/Parser/ms-inline-asm.c
===================================================================
--- test/Parser/ms-inline-asm.c
+++ test/Parser/ms-inline-asm.c
@@ -48,6 +48,9 @@
 void t11() {
   do { __asm mov eax, 0 __asm { __asm mov edx, 1 } } while(0);
 }
+void t12() {
+  __asm jmp label // expected-error {{use of undeclared label 'label'}}
+}
 int t_fail() { // expected-note {{to match this}}
   __asm 
   __asm { // expected-error 2 {{expected}} expected-note {{to match this}}
Index: test/Sema/ms-inline-asm.c
===================================================================
--- test/Sema/ms-inline-asm.c
+++ test/Sema/ms-inline-asm.c
@@ -29,7 +29,7 @@
   }
   f();
   __asm {
-    mov eax, TYPE bar // expected-error {{unable to lookup expression}}
+    mov eax, TYPE bar // expected-error {{unable to lookup expression}} expected-error {{use of undeclared label 'bar'}}
   }
 }
 
@@ -80,9 +80,10 @@
 } A;
 
 void t3() {
-  __asm { mov eax, [eax] UndeclaredId } // expected-error {{unknown token in expression}}
+  __asm { mov eax, [eax] UndeclaredId } // expected-error {{unknown token in expression}} expected-error {{use of undeclared label 'UndeclaredId'}}
 
   // FIXME: Only emit one diagnostic here.
+  // expected-error@+3 {{use of undeclared label 'A'}}
   // expected-error@+2 {{unexpected type name 'A': expected expression}}
   // expected-error@+1 {{unknown token in expression}}
   __asm { mov eax, [eax] A }
@@ -105,12 +106,45 @@
 }
 
 __declspec(naked) int t5(int x) { // expected-note {{attribute is here}}
-  asm { movl eax, x } // expected-error {{parameter references not allowed in naked functions}}
+  asm { movl eax, x } // expected-error {{parameter references not allowed in naked functions}} expected-error {{use of undeclared label 'x'}}
   asm { retl }
 }
 
 int y;
 __declspec(naked) int t6(int x) {
   asm { mov eax, y } // No error.
   asm { ret }
 }
+
+void t7() {
+  __asm {
+    foo: // expected-note {{inline assembly label 'foo' declared here}}
+    mov eax, 0
+  }
+  goto foo; // expected-error {{cannot jump from this goto statement to label 'foo' inside an inline assembly block}}
+}
+
+void t8() {
+  __asm foo: // expected-note {{inline assembly label 'foo' declared here}}
+  __asm mov eax, 0
+  goto foo; // expected-error {{cannot jump from this goto statement to label 'foo' inside an inline assembly block}}
+}
+
+void t9() {
+  goto foo; // expected-error {{cannot jump from this goto statement to label 'foo' inside an inline assembly block}}
+  __asm {
+    foo: // expected-note {{inline assembly label 'foo' declared here}}
+    mov eax, 0
+  }
+}
+
+void t10() {
+  goto foo; // expected-error {{cannot jump from this goto statement to label 'foo' inside an inline assembly block}}
+  __asm foo: // expected-note {{inline assembly label 'foo' declared here}}
+  __asm mov eax, 0
+}
+
+void t11() {
+foo:
+  __asm mov eax, foo // expected-error {{use of undeclared label 'foo'}}
+}
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to