void updated this revision to Diff 228594.
void added a comment.

Emit asm goto fallthrough early so that any value extracts will show up in the
fallthrough block and not directly after the callbr.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D69876/new/

https://reviews.llvm.org/D69876

Files:
  clang/include/clang/AST/Stmt.h
  clang/lib/AST/Stmt.cpp
  clang/lib/CodeGen/CGStmt.cpp
  clang/lib/Parse/ParseStmtAsm.cpp
  clang/lib/Sema/SemaStmtAsm.cpp
  clang/test/CodeGen/asm-goto.c
  clang/test/Parser/asm-goto.c
  clang/test/Parser/asm-goto.cpp
  clang/test/Sema/asm-goto.cpp

Index: clang/test/Sema/asm-goto.cpp
===================================================================
--- clang/test/Sema/asm-goto.cpp
+++ clang/test/Sema/asm-goto.cpp
@@ -1,53 +1,51 @@
 // RUN: %clang_cc1 %s -triple i386-pc-linux-gnu -verify -fsyntax-only
 // RUN: %clang_cc1 %s -triple x86_64-pc-linux-gnu -verify -fsyntax-only
 
-struct NonTrivial {
-  ~NonTrivial();
+struct S {
+  ~S();
   int f(int);
 private:
   int k;
 };
-void JumpDiagnostics(int n) {
-// expected-error@+1 {{cannot jump from this goto statement to its label}}
+void test1(int n) {
+  // expected-error@+1 {{cannot jump from this goto statement to its label}}
   goto DirectJump;
-// expected-note@+1 {{jump bypasses variable with a non-trivial destructor}}
-  NonTrivial tnp1;
+  // expected-note@+1 {{jump bypasses variable with a non-trivial destructor}}
+  S s1;
 
 DirectJump:
-// expected-error@+1 {{cannot jump from this asm goto statement to one of its possible targets}}
+  // expected-error@+1 {{cannot jump from this asm goto statement to one of its possible targets}}
   asm goto("jmp %l0;" ::::Later);
-// expected-note@+1 {{jump bypasses variable with a non-trivial destructor}}
-  NonTrivial tnp2;
-// expected-note@+1 {{possible target of asm goto statement}}
+  // expected-note@+1 {{jump bypasses variable with a non-trivial destructor}}
+  S s2;
+  // expected-note@+1 {{possible target of asm goto statement}}
 Later:
   return;
 }
 
-struct S { ~S(); };
-void foo(int a) {
+struct T { ~T(); };
+void test2(int a) {
   if (a) {
 FOO:
-// expected-note@+2 {{jump exits scope of variable with non-trivial destructor}}
-// expected-note@+1 {{jump exits scope of variable with non-trivial destructor}}
-    S s;
-    void *p = &&BAR;
-// expected-error@+1 {{cannot jump from this asm goto statement to one of its possible targets}}
-  asm goto("jmp %l0;" ::::BAR);
-// expected-error@+1 {{cannot jump from this indirect goto statement to one of its possible targets}}
+    // expected-note@+2 {{jump exits scope of variable with non-trivial destructor}}
+    // expected-note@+1 {{jump exits scope of variable with non-trivial destructor}}
+    T t;
+    void *p = &&bar;
+  // expected-error@+1 {{cannot jump from this asm goto statement to one of its possible targets}}
+  asm goto("jmp %l0;" ::::bar);
+    // expected-error@+1 {{cannot jump from this indirect goto statement to one of its possible targets}}
     goto *p;
     p = &&FOO;
     goto *p;
     return;
   }
-// expected-note@+2 {{possible target of asm goto statement}}
-// expected-note@+1 {{possible target of indirect goto statement}}
-BAR:
+  // expected-note@+2 {{possible target of asm goto statement}}
+  // expected-note@+1 {{possible target of indirect goto statement}}
+bar:
   return;
 }
 
-
-//Asm goto:
-int test16(int n)
+int test3(int n)
 {
   // expected-error@+2 {{cannot jump from this asm goto statement to one of its possible targets}}
   // expected-error@+1 {{cannot jump from this asm goto statement to one of its possible targets}}
@@ -57,7 +55,7 @@
   return ({int a[n];label_true: 2;});
   // expected-note@+1 {{jump bypasses initialization of variable length array}}
   int b[n];
-// expected-note@+1 {{possible target of asm goto statement}}
+  // expected-note@+1 {{possible target of asm goto statement}}
 loop:
   return 0;
 }
Index: clang/test/Parser/asm-goto.cpp
===================================================================
--- clang/test/Parser/asm-goto.cpp
+++ clang/test/Parser/asm-goto.cpp
@@ -1,14 +1,54 @@
 // RUN: %clang_cc1 -triple i386-pc-linux-gnu -fsyntax-only -verify -std=c++11 %s
 // RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fsyntax-only -verify -std=c++11 %s
 
-int zoo ()
-{
+int a, b, c, d, e, f, g, h, i, j, k, l;
+
+void test1(void) {
+  __asm__ volatile goto (""
+            :: [a] "r" (a), [b] "r" (b), [c] "r" (c), [d] "r" (d),
+               [e] "r" (e), [f] "r" (f), [g] "r" (g), [h] "r" (h),
+               [i] "r" (i), [j] "r" (j), [k] "r" (k), [l] "r" (l)
+            ::lab1,lab2);
+lab1: return;
+lab2: return;
+}
+
+void test2(void) {
+  __asm__ volatile goto (""
+            :: [a] "r,m" (a), [b] "r,m" (b), [c] "r,m" (c), [d] "r,m" (d),
+               [e] "r,m" (e), [f] "r,m" (f), [g] "r,m" (g), [h] "r,m" (h),
+               [i] "r,m" (i), [j] "r,m" (j), [k] "r,m" (k), [l] "r,m" (l)
+            :: lab);
+  lab: return;
+}
+
+int test3(int x) {
+  __asm__ volatile goto ("decl %0; jnz %l[a]"
+                         : "=r" (x) : "m" (x) : "memory" : a);
+a:
+  return -x;
+}
+
+int test4(int x) {
+  int y;
+  if (x > 42)
+    __asm__ volatile goto ("decl %0; jnz %l[a]"
+                           : "=r" (x), "=r" (y) : "m" (x) : "memory" : a);
+  else
+    __asm__ volatile goto ("decl %0; jnz %l[b]"
+                           : "=r" (x), "=r" (y) : "m" (x) : "memory" : b);
+  x = y + 42;
+a:
+  return -x;
+b:
+  return +x;
+}
+
+int test5(void) {
   int x,cond,*e;
   // expected-error@+1 {{expected ')'}}
   asm ("mov %[e], %[e]" : : [e] "rm" (*e)::a)
-  // expected-error@+1  {{'asm goto' cannot have output constraints}}
-  asm goto ("decl %0; jnz %l[a]" :"=r"(x): "m"(x) : "memory" : a);
-  // expected-error@+1 {{expected identifie}}
+  // expected-error@+1 {{expected identifier}}
   asm goto ("decl %0;" :: "m"(x) : "memory" : );
   // expected-error@+1  {{expected ':'}}
   asm goto ("decl %0;" :: "m"(x) : "memory" );
@@ -26,28 +66,24 @@
   return 0;
 }
 
-
-int a, b, c, d, e, f, g, h, i, j, k, l;
-
-void
-fgoto1 (void)
-{
-  __asm__ volatile goto (""
-            :: [a] "r" (a), [b] "r" (b), [c] "r" (c), [d] "r" (d),
-               [e] "r" (e), [f] "r" (f), [g] "r" (g), [h] "r" (h),
-               [i] "r" (i), [j] "r" (j), [k] "r" (k), [l] "r" (l)
-            ::lab1,lab2);
-lab1: return;
-lab2: return;
-}
-
-void
-fgoto2 (void)
-{
-  __asm__ volatile goto (""
-            :: [a] "r,m" (a), [b] "r,m" (b), [c] "r,m" (c), [d] "r,m" (d),
-               [e] "r,m" (e), [f] "r,m" (f), [g] "r,m" (g), [h] "r,m" (h),
-               [i] "r,m" (i), [j] "r,m" (j), [k] "r,m" (k), [l] "r,m" (l)
-            :: lab);
-  lab: return;
+int test6(int y) {
+  int x,cond,*e;
+  // expected-error@+1 {{expected ')'}}
+  asm ("mov %[e], %[e]" : "=r" (y) : [e] "rm" (*e), "r" (y) :: a)
+  // expected-error@+1 {{expected identifier}}
+  asm goto ("decl %0;" : "=r" (y) : "m" (x), "r" (y) : "memory" :);
+  // expected-error@+1  {{expected ':'}}
+  asm goto ("decl %0;" : "=r" (y) : "m" (x), "r" (y) : "memory");
+  // expected-error@+1 {{use of undeclared label 'x'}}
+  asm goto ("decl %0;" : "=r" (y) : "m" (x), "r" (y) : "memory" : x);
+  // expected-error@+1 {{use of undeclared label 'b'}}
+  asm goto ("decl %0;" : "=r" (y) : "m" (x), "r" (y) : "memory" : b);
+  // expected-error@+1 {{invalid operand number in inline asm string}}
+  asm goto ("testl %0, %0; jne %l5;" : "=r" (y) : "r" (cond), "r" (y) :: label_true, loop);
+  // expected-error@+1 {{unknown symbolic operand name in inline assembly string}}
+  asm goto ("decl %0; jnz %l[b]" : "=r" (y) : "m" (x), "r" (y) : "memory" : a);
+label_true:
+loop:
+a:
+  return 0;
 }
Index: clang/test/Parser/asm-goto.c
===================================================================
--- clang/test/Parser/asm-goto.c
+++ clang/test/Parser/asm-goto.c
@@ -5,12 +5,9 @@
 #error Extension 'gnu_asm' should be available by default
 #endif
 
-
 int a, b, c, d, e, f, g, h, i, j, k, l;
 
-void
-fgoto1 (void)
-{
+void test(void) {
   __asm__ volatile goto (""
             :: [a] "r" (a), [b] "r" (b), [c] "r" (c), [d] "r" (d),
                [e] "r" (e), [f] "r" (f), [g] "r" (g), [h] "r" (h),
@@ -20,9 +17,7 @@
 lab2: return;
 }
 
-void
-fgoto2 (void)
-{
+void test2(void) {
   __asm__ volatile goto (""
             :: [a] "r,m" (a), [b] "r,m" (b), [c] "r,m" (c), [d] "r,m" (d),
                [e] "r,m" (e), [f] "r,m" (f), [g] "r,m" (g), [h] "r,m" (h),
@@ -31,14 +26,33 @@
   lab: return;
 }
 
-int zoo ()
-{
+int test3(int x) {
+  __asm__ volatile goto ("decl %0; jnz %l[a]"
+                         : "=r" (x) : "m" (x) : "memory" : a);
+a:
+  return -x;
+}
+
+int test4(int x) {
+  int y;
+  if (x > 42)
+    __asm__ volatile goto ("decl %0; jnz %l[a]"
+                           : "=r" (x), "=r" (y) : "m" (x) : "memory" : a);
+  else
+    __asm__ volatile goto ("decl %0; jnz %l[b]"
+                           : "=r" (x), "=r" (y) : "m" (x) : "memory" : b);
+  x = y + 42;
+a:
+  return -x;
+b:
+  return +x;
+}
+
+int test5(void) {
   int x,cond,*e;
   // expected-error@+1 {{expected ')'}}
   asm ("mov %[e], %[e]" : : [e] "rm" (*e)::a)
-  // expected-error@+1 {{'asm goto' cannot have output constraints}}
-  asm goto ("decl %0; jnz %l[a]" :"=r"(x): "m"(x) : "memory" : a);
-  // expected-error@+1 {{expected identifie}}
+  // expected-error@+1 {{expected identifier}}
   asm goto ("decl %0;" :: "m"(x) : "memory" : );
   // expected-error@+1 {{expected ':'}}
   asm goto ("decl %0;" :: "m"(x) : "memory" );
@@ -55,3 +69,25 @@
 loop:
   return 0;
 }
+
+int test6(int y) {
+  int x,cond,*e;
+  // expected-error@+1 {{expected ')'}}
+  asm ("mov %[e], %[e]" : "=r" (y) : [e] "rm" (*e), "r" (y) :: a)
+  // expected-error@+1 {{expected identifier}}
+  asm goto ("decl %0;" : "=r" (y) : "m" (x), "r" (y) : "memory" :);
+  // expected-error@+1  {{expected ':'}}
+  asm goto ("decl %0;" : "=r" (y) : "m" (x), "r" (y) : "memory");
+  // expected-error@+1 {{use of undeclared label 'x'}}
+  asm goto ("decl %0;" : "=r" (y) : "m" (x), "r" (y) : "memory" : x);
+  // expected-error@+1 {{use of undeclared label 'b'}}
+  asm goto ("decl %0;" : "=r" (y) : "m" (x), "r" (y) : "memory" : b);
+  // expected-error@+1 {{invalid operand number in inline asm string}}
+  asm goto ("testl %0, %0; jne %l5;" : "=r" (y) : "r" (cond), "r" (y) :: label_true, loop);
+  // expected-error@+1 {{unknown symbolic operand name in inline assembly string}}
+  asm goto ("decl %0; jnz %l[b]" : "=r" (y) : "m" (x), "r" (y) : "memory" : a);
+label_true:
+loop:
+a:
+  return 0;
+}
Index: clang/test/CodeGen/asm-goto.c
===================================================================
--- clang/test/CodeGen/asm-goto.c
+++ clang/test/CodeGen/asm-goto.c
@@ -2,8 +2,7 @@
 // RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -O0 -emit-llvm %s -o - | FileCheck %s
 // RUN: %clang_cc1 -triple i386-pc-linux-gnu -O0 -emit-llvm %s -o - | FileCheck %s
 
-int foo(int cond)
-{
+int test1(int cond) {
   // CHECK: callbr void asm sideeffect
   // CHECK: to label %asm.fallthrough [label %label_true, label %loop]
   // CHECK: asm.fallthrough:
@@ -18,3 +17,35 @@
 label_true:
   return 1;
 }
+
+int test2(int cond) {
+  // CHECK: callbr i32 asm sideeffect
+  // CHECK: to label %asm.fallthrough [label %label_true, label %loop]
+  // CHECK: asm.fallthrough:
+  asm volatile goto("testl %0, %0; jne %l1;" : "=r"(cond) : "r"(cond) :: label_true, loop);
+  asm volatile goto("testl %0, %0; jne %l1;" : "=r"(cond) : "r"(cond) :: label_true, loop);
+  // CHECK: callbr i32 asm sideeffect
+  // CHECK: to label %asm.fallthrough1 [label %label_true, label %loop]
+  // CHECK: asm.fallthrough1:
+  return 0;
+loop:
+  return 0;
+label_true:
+  return 1;
+}
+
+int test3(int out1, int out2) {
+  // CHECK: callbr { i32, i32 } asm sideeffect
+  // CHECK: to label %asm.fallthrough [label %label_true, label %loop]
+  // CHECK: asm.fallthrough:
+  asm volatile goto("testl %0, %0; jne %l1;" : "=r"(out1), "=r"(out2) : "r"(out1) :: label_true, loop);
+  asm volatile goto("testl %0, %0; jne %l1;" : "=r"(out1), "=r"(out2) : "r"(out1) :: label_true, loop);
+  // CHECK: callbr { i32, i32 } asm sideeffect
+  // CHECK: to label %asm.fallthrough2 [label %label_true, label %loop]
+  // CHECK: asm.fallthrough2:
+  return 0;
+loop:
+  return 0;
+label_true:
+  return 1;
+}
Index: clang/lib/Sema/SemaStmtAsm.cpp
===================================================================
--- clang/lib/Sema/SemaStmtAsm.cpp
+++ clang/lib/Sema/SemaStmtAsm.cpp
@@ -473,10 +473,10 @@
 
     // Look for the correct constraint index.
     unsigned ConstraintIdx = Piece.getOperandNo();
-    // Labels are the last in the Exprs list.
-    if (NS->isAsmGoto() && ConstraintIdx >= NS->getNumInputs())
-      continue;
     unsigned NumOperands = NS->getNumOutputs() + NS->getNumInputs();
+    // Labels are the last in the Exprs list.
+    if (NS->isAsmGoto() && ConstraintIdx >= NumOperands)
+      continue;
     // Look for the (ConstraintIdx - NumOperands + 1)th constraint with
     // modifier '+'.
     if (ConstraintIdx >= NumOperands) {
Index: clang/lib/Parse/ParseStmtAsm.cpp
===================================================================
--- clang/lib/Parse/ParseStmtAsm.cpp
+++ clang/lib/Parse/ParseStmtAsm.cpp
@@ -764,12 +764,6 @@
     AteExtraColon = Tok.is(tok::coloncolon);
     ConsumeToken();
 
-    if (!AteExtraColon && isGotoAsm && Tok.isNot(tok::colon)) {
-      Diag(Tok, diag::err_asm_goto_cannot_have_output);
-      SkipUntil(tok::r_paren, StopAtSemi);
-      return StmtError();
-    }
-
     if (!AteExtraColon && ParseAsmOperandsOpt(Names, Constraints, Exprs))
       return StmtError();
   }
Index: clang/lib/CodeGen/CGStmt.cpp
===================================================================
--- clang/lib/CodeGen/CGStmt.cpp
+++ clang/lib/CodeGen/CGStmt.cpp
@@ -2233,8 +2233,7 @@
           Constraints += ',';
         Constraints += 'X';
       }
-      StringRef Name = "asm.fallthrough";
-      Fallthrough = createBasicBlock(Name);
+      Fallthrough = createBasicBlock("asm.fallthrough");
     }
   }
 
@@ -2284,9 +2283,9 @@
   if (IsGCCAsmGoto) {
     llvm::CallBrInst *Result =
         Builder.CreateCallBr(IA, Fallthrough, Transfer, Args);
+    EmitBlock(Fallthrough);
     UpdateAsmCallInst(cast<llvm::CallBase>(*Result), HasSideEffect, ReadOnly,
                       ReadNone, S, ResultRegTypes, *this, RegResults);
-    EmitBlock(Fallthrough);
   } else {
     llvm::CallInst *Result =
         Builder.CreateCall(IA, Args, getBundlesForFunclet(IA));
Index: clang/lib/AST/Stmt.cpp
===================================================================
--- clang/lib/AST/Stmt.cpp
+++ clang/lib/AST/Stmt.cpp
@@ -456,7 +456,7 @@
 }
 
 AddrLabelExpr *GCCAsmStmt::getLabelExpr(unsigned i) const {
-  return cast<AddrLabelExpr>(Exprs[i + NumInputs]);
+  return cast<AddrLabelExpr>(Exprs[i + NumOutputs + NumInputs]);
 }
 
 StringRef GCCAsmStmt::getLabelName(unsigned i) const {
@@ -522,7 +522,7 @@
 
   for (unsigned i = 0, e = getNumLabels(); i != e; ++i)
     if (getLabelName(i) == SymbolicName)
-      return i + getNumInputs();
+      return i + getNumOutputs() + getNumInputs();
 
   // Not found.
   return -1;
Index: clang/include/clang/AST/Stmt.h
===================================================================
--- clang/include/clang/AST/Stmt.h
+++ clang/include/clang/AST/Stmt.h
@@ -3013,7 +3013,7 @@
   }
 
   IdentifierInfo *getLabelIdentifier(unsigned i) const {
-    return Names[i + NumInputs];
+    return Names[i + NumOutputs + NumInputs];
   }
 
   AddrLabelExpr *getLabelExpr(unsigned i) const;
@@ -3024,11 +3024,11 @@
   using labels_const_range = llvm::iterator_range<const_labels_iterator>;
 
   labels_iterator begin_labels() {
-    return &Exprs[0] + NumInputs;
+    return &Exprs[0] + NumOutputs + NumInputs;
   }
 
   labels_iterator end_labels() {
-    return &Exprs[0] + NumInputs + NumLabels;
+    return &Exprs[0] + NumOutputs + NumInputs + NumLabels;
   }
 
   labels_range labels() {
@@ -3036,11 +3036,11 @@
   }
 
   const_labels_iterator begin_labels() const {
-    return &Exprs[0] + NumInputs;
+    return &Exprs[0] + NumOutputs + NumInputs;
   }
 
   const_labels_iterator end_labels() const {
-    return &Exprs[0] + NumInputs + NumLabels;
+    return &Exprs[0] + NumOutputs + NumInputs + NumLabels;
   }
 
   labels_const_range labels() const {
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to