]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Backport of the "asm inline" patches
authorSegher Boessenkool <segher@kernel.crashing.org>
Wed, 2 Jan 2019 22:49:04 +0000 (23:49 +0100)
committerSegher Boessenkool <segher@gcc.gnu.org>
Wed, 2 Jan 2019 22:49:04 +0000 (23:49 +0100)
From-SVN: r267536

26 files changed:
gcc/ChangeLog
gcc/c/ChangeLog
gcc/c/c-parser.c
gcc/c/c-tree.h
gcc/c/c-typeck.c
gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/parser.c
gcc/cp/pt.c
gcc/cp/semantics.c
gcc/doc/extend.texi
gcc/gimple-pretty-print.c
gcc/gimple.h
gcc/gimplify.c
gcc/ipa-icf-gimple.c
gcc/testsuite/ChangeLog
gcc/testsuite/c-c++-common/torture/asm-inline.c [new file with mode: 0644]
gcc/testsuite/g++.dg/asm-qual-1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/asm-qual-2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/asm-qual-3.C [new file with mode: 0644]
gcc/testsuite/gcc.dg/asm-qual-1.c
gcc/testsuite/gcc.dg/asm-qual-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/asm-qual-3.c [new file with mode: 0644]
gcc/tree-core.h
gcc/tree-inline.c
gcc/tree.h

index 5d1bf431b41cd48b13b1cf77763d7c457ec9190e..44bc7f5c753a59fc7132d0a8bbafbead7b2193a4 100644 (file)
@@ -1,3 +1,32 @@
+2019-01-02  Segher Boessenkool  <segher@kernel.crashing.org>
+
+       Backport from trunk
+       2018-12-06  Segher Boessenkool  <segher@kernel.crashing.org>
+
+       PR inline-asm/55681
+       * doc/extend.texi (Basic Asm): Update grammar.
+       (Extended Asm): Update grammar.
+
+       Backport from trunk
+       2018-12-06  Segher Boessenkool  <segher@kernel.crashing.org>
+
+       * doc/extend.texi (Using Assembly Language with C): Document asm inline.
+       (Size of an asm): Fix typo.  Document asm inline.
+       * gimple-pretty-print.c (dump_gimple_asm): Handle asm inline.
+       * gimple.h (enum gf_mask): Add GF_ASM_INLINE.
+       (gimple_asm_set_volatile): Fix typo.
+       (gimple_asm_inline_p): New.
+       (gimple_asm_set_inline): New.
+       * gimplify.c (gimplify_asm_expr): Propagate the asm inline flag from
+       tree to gimple.
+       * ipa-icf-gimple.c (func_checker::compare_gimple_asm): Compare the
+       gimple_asm_inline_p flag, too.
+       * tree-core.h (tree_base): Document that protected_flag is ASM_INLINE_P
+       in an ASM_EXPR.
+       * tree-inline.c (estimate_num_insns): If gimple_asm_inline_p return
+       a minimum size for an asm.
+       * tree.h (ASM_INLINE_P): New.
+
 2018-12-30  Iain Sandoe  <iain@sandoe.co.uk>
 
        backport from mainline.
index 2f2795165add8ae1b5477ee26f711e6d154dfd9a..86a4c9659736179828f6133d37aaf84be2034494 100644 (file)
@@ -1,3 +1,55 @@
+2018-01-02  Segher Boessenkool  <segher@kernel.crashing.org>
+
+       Backport from trunk
+       2018-12-06  Segher Boessenkool  <segher@kernel.crashing.org>
+
+       PR inline-asm/55681
+       * c-parser.c (c_parser_asm_statement): Update grammar.  Allow any
+       combination of volatile and goto, in any order, without repetitions.
+
+       Backport from trunk
+       2018-12-06  Segher Boessenkool  <segher@kernel.crashing.org>
+
+       * c-parser.c (c_parser_asm_statement): Detect the inline keyword
+       after asm.  Pass a flag for it to build_asm_expr.
+       * c-tree.h (build_asm_expr): Update declaration.
+       * c-typeck.c (build_asm_stmt): Add is_inline parameter.  Use it to
+       set ASM_INLINE_P.
+
+       Backport from trunk
+       2018-12-08  Segher Boessenkool  <segher@kernel.crashing.org>
+
+       * c-parser (c_parser_asm_statement) [RID_INLINE]: Delete stray line
+       setting "quals".
+
+       Backport from trunk
+       2018-12-19  Segher Boessenkool  <segher@kernel.crashing.org>
+
+       * c-parser.c (c_parser_asm_statement): Rewrite the loop to work without
+       "done" boolean variable.
+
+       Backport from trunk
+       2018-12-19  Segher Boessenkool  <segher@kernel.crashing.org>
+
+       * c-parser.c (c_parser_asm_statement): Keep track of the location each
+       asm qualifier is first seen; use that to give nicer "duplicate asm
+       qualifier" messages.  Delete 'quals" variable, instead pass the
+       "is_volatile_ flag to build_asm_stmt directly.
+       * c-tree.h (build_asm_stmt): Make the first arg bool instead of tree.
+       * c-typeck.c (build_asm_stmt): Ditto; adjust.
+
+       Backport from trunk
+       2018-12-19  Segher Boessenkool  <segher@kernel.crashing.org>
+
+       * c-parser.c (c_parser_asm_statement) <RID_CONST, RID_RESTRICT>: Give
+       a more specific error message (instead of just falling through).
+
+       And extra for the backport
+       2019-01-02  Segher Boessenkool  <segher@kernel.crashing.org>
+
+       * c-parser.c (c_parser_asm_statement): Output a warning instead of an
+       error for const and restrict.
+
 2018-12-06  Release Manager
 
        * GCC 7.4.0 released.
index 101afb8e35f0a896ef3d6c61a244aacbdb4776ac..86195c53249ef4937b647644bfd6d698824daf12 100644 (file)
@@ -6089,61 +6089,104 @@ c_parser_for_statement (c_parser *parser, bool ivdep, bool *if_p)
 }
 
 /* Parse an asm statement, a GNU extension.  This is a full-blown asm
-   statement with inputs, outputs, clobbers, and volatile tag
-   allowed.
+   statement with inputs, outputs, clobbers, and volatile, inline, and goto
+   tags allowed.
+
+   asm-qualifier:
+     volatile
+     inline
+     goto
+
+   asm-qualifier-list:
+     asm-qualifier-list asm-qualifier
+     asm-qualifier
 
    asm-statement:
-     asm type-qualifier[opt] ( asm-argument ) ;
-     asm type-qualifier[opt] goto ( asm-goto-argument ) ;
+     asm asm-qualifier-list[opt] ( asm-argument ) ;
 
    asm-argument:
      asm-string-literal
      asm-string-literal : asm-operands[opt]
      asm-string-literal : asm-operands[opt] : asm-operands[opt]
-     asm-string-literal : asm-operands[opt] : asm-operands[opt] : asm-clobbers[opt]
-
-   asm-goto-argument:
+     asm-string-literal : asm-operands[opt] : asm-operands[opt] \
+       : asm-clobbers[opt]
      asm-string-literal : : asm-operands[opt] : asm-clobbers[opt] \
        : asm-goto-operands
 
-   Qualifiers other than volatile are accepted in the syntax but
-   warned for.  */
+   The form with asm-goto-operands is valid if and only if the
+   asm-qualifier-list contains goto, and is the only allowed form in that case.
+   Duplicate asm-qualifiers are not allowed.  */
 
 static tree
 c_parser_asm_statement (c_parser *parser)
 {
-  tree quals, str, outputs, inputs, clobbers, labels, ret;
-  bool simple, is_goto;
+  tree str, outputs, inputs, clobbers, labels, ret;
+  bool simple;
   location_t asm_loc = c_parser_peek_token (parser)->location;
   int section, nsections;
 
   gcc_assert (c_parser_next_token_is_keyword (parser, RID_ASM));
   c_parser_consume_token (parser);
-  if (c_parser_next_token_is_keyword (parser, RID_VOLATILE))
-    {
-      quals = c_parser_peek_token (parser)->value;
-      c_parser_consume_token (parser);
-    }
-  else if (c_parser_next_token_is_keyword (parser, RID_CONST)
-          || c_parser_next_token_is_keyword (parser, RID_RESTRICT))
-    {
-      warning_at (c_parser_peek_token (parser)->location,
-                 0,
-                 "%E qualifier ignored on asm",
-                 c_parser_peek_token (parser)->value);
-      quals = NULL_TREE;
-      c_parser_consume_token (parser);
-    }
-  else
-    quals = NULL_TREE;
 
-  is_goto = false;
-  if (c_parser_next_token_is_keyword (parser, RID_GOTO))
+  /* Handle the asm-qualifier-list.  */
+  location_t volatile_loc = UNKNOWN_LOCATION;
+  location_t inline_loc = UNKNOWN_LOCATION;
+  location_t goto_loc = UNKNOWN_LOCATION;
+  for (;;)
     {
-      c_parser_consume_token (parser);
-      is_goto = true;
+      c_token *token = c_parser_peek_token (parser);
+      location_t loc = token->location;
+      switch (token->keyword)
+       {
+       case RID_VOLATILE:
+         if (volatile_loc)
+           {
+             error_at (loc, "duplicate asm qualifier %qE", token->value);
+             inform (volatile_loc, "first seen here");
+           }
+         else
+           volatile_loc = loc;
+         c_parser_consume_token (parser);
+         continue;
+
+       case RID_INLINE:
+         if (inline_loc)
+           {
+             error_at (loc, "duplicate asm qualifier %qE", token->value);
+             inform (inline_loc, "first seen here");
+           }
+         else
+           inline_loc = loc;
+         c_parser_consume_token (parser);
+         continue;
+
+       case RID_GOTO:
+         if (goto_loc)
+           {
+             error_at (loc, "duplicate asm qualifier %qE", token->value);
+             inform (goto_loc, "first seen here");
+           }
+         else
+           goto_loc = loc;
+         c_parser_consume_token (parser);
+         continue;
+
+       case RID_CONST:
+       case RID_RESTRICT:
+         warning_at (loc, 0, "%qE is not an asm qualifier", token->value);
+         c_parser_consume_token (parser);
+         continue;
+
+       default:
+         break;
+       }
+      break;
     }
 
+  bool is_volatile = (volatile_loc != UNKNOWN_LOCATION);
+  bool is_inline = (inline_loc != UNKNOWN_LOCATION);
+  bool is_goto = (goto_loc != UNKNOWN_LOCATION);
+
   /* ??? Follow the C++ parser rather than using the
      lex_untranslated_string kludge.  */
   parser->lex_untranslated_string = true;
@@ -6216,8 +6259,9 @@ c_parser_asm_statement (c_parser *parser)
   if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
     c_parser_skip_to_end_of_block_or_statement (parser);
 
-  ret = build_asm_stmt (quals, build_asm_expr (asm_loc, str, outputs, inputs,
-                                              clobbers, labels, simple));
+  ret = build_asm_stmt (is_volatile,
+                       build_asm_expr (asm_loc, str, outputs, inputs,
+                                       clobbers, labels, simple, is_inline));
 
  error:
   parser->lex_untranslated_string = false;
index 5fa32a48f294e0a465f764ba1f30393240464115..eef26f89f027ad0b8e652058a2fec83337187caa 100644 (file)
@@ -659,8 +659,9 @@ extern tree build_compound_literal (location_t, tree, tree, bool);
 extern void check_compound_literal_type (location_t, struct c_type_name *);
 extern tree c_start_case (location_t, location_t, tree, bool);
 extern void c_finish_case (tree, tree);
-extern tree build_asm_expr (location_t, tree, tree, tree, tree, tree, bool);
-extern tree build_asm_stmt (tree, tree);
+extern tree build_asm_expr (location_t, tree, tree, tree, tree, tree, bool,
+                           bool);
+extern tree build_asm_stmt (bool, tree);
 extern int c_types_compatible_p (tree, tree);
 extern tree c_begin_compound_stmt (bool);
 extern tree c_end_compound_stmt (location_t, tree, bool);
index 66a58a81e71fe1c92bd2c516f2d929e1d8eb48e6..fd9fa2d5a198ed5666517a64aaeef9f778a39922 100644 (file)
@@ -9669,9 +9669,9 @@ process_init_element (location_t loc, struct c_expr value, bool implicit,
    (guaranteed to be 'volatile' or null) and ARGS (represented using
    an ASM_EXPR node).  */
 tree
-build_asm_stmt (tree cv_qualifier, tree args)
+build_asm_stmt (bool is_volatile, tree args)
 {
-  if (!ASM_VOLATILE_P (args) && cv_qualifier)
+  if (is_volatile)
     ASM_VOLATILE_P (args) = 1;
   return add_stmt (args);
 }
@@ -9680,10 +9680,12 @@ build_asm_stmt (tree cv_qualifier, tree args)
    some INPUTS, and some CLOBBERS.  The latter three may be NULL.
    SIMPLE indicates whether there was anything at all after the
    string in the asm expression -- asm("blah") and asm("blah" : )
-   are subtly different.  We use a ASM_EXPR node to represent this.  */
+   are subtly different.  We use a ASM_EXPR node to represent this.
+   LOC is the location of the asm, and IS_INLINE says whether this
+   is asm inline.  */
 tree
 build_asm_expr (location_t loc, tree string, tree outputs, tree inputs,
-               tree clobbers, tree labels, bool simple)
+               tree clobbers, tree labels, bool simple, bool is_inline)
 {
   tree tail;
   tree args;
@@ -9801,6 +9803,7 @@ build_asm_expr (location_t loc, tree string, tree outputs, tree inputs,
      as volatile.  */
   ASM_INPUT_P (args) = simple;
   ASM_VOLATILE_P (args) = (noutputs == 0);
+  ASM_INLINE_P (args) = is_inline;
 
   return args;
 }
index 1830969cbd26ac9125c51e3bf2adb19a9703b410..c53684fafd614d38dac4fbd2ff78284b72a1ae96 100644 (file)
@@ -1,3 +1,49 @@
+2018-01-02  Segher Boessenkool  <segher@kernel.crashing.org>
+
+       Backport from trunk
+       2018-12-06  Segher Boessenkool  <segher@kernel.crashing.org>
+
+       PR inline-asm/55681
+       * parser.c (cp_parser_asm_definition): Update grammar.  Allow any
+       combination of volatile and goto, in any order, without repetitions.
+
+       Backport from trunk
+       2018-12-06  Segher Boessenkool  <segher@kernel.crashing.org>
+
+       * cp-tree.h (finish_asm_stmt): Update declaration.
+       * parser.c (cp_parser_asm_definition): Detect the inline keyword
+       after asm.  Pass a flag for it to finish_asm_stmt.
+       * pt.c (tsubst_expr): Pass the ASM_INLINE_P flag to finish_asm_stmt.
+       * semantics.c (finish_asm_stmt): Add inline_p parameter.  Use it to
+       set ASM_INLINE_P.
+
+       Backport from trunk
+       2018-12-19  Segher Boessenkool  <segher@kernel.crashing.org>
+
+       * parser.c (cp_parser_asm_definition): Rewrite the loop to work without
+       "done" boolean variable.
+
+       Backport from trunk
+       2018-12-19  Segher Boessenkool  <segher@kernel.crashing.org>
+
+       * parser.c (cp_parser_asm_definition): Rewrite the loop to work without
+       "done" boolean variable.
+       * parser.c (cp_parser_asm_definition): Keep track of the location each
+       asm qualifier is first seen; use that to give nicer "duplicate asm
+       qualifier" messages.
+
+       Backport from trunk
+       2018-12-19  Segher Boessenkool  <segher@kernel.crashing.org>
+
+       * parser.c (cp_parser_asm_definition) <RID_CONST, RID_RESTRICT>: Give
+       a more specific error message (instead of just falling through).
+
+       Backport from trunk
+       2018-12-10  Segher Boessenkool  <segher@kernel.crashing.org>
+
+       * parser.c (cp_parser_asm_definition): Do not allow any asm qualifiers
+       on top-level asm.
+
 2018-12-06  Release Manager
 
        * GCC 7.4.0 released.
index 664def60405864b80ab32feab0c8271f97df11cb..842d410f8421914c286ab129e3d687ba567d2015 100644 (file)
@@ -6455,7 +6455,7 @@ extern tree begin_compound_stmt                   (unsigned int);
 
 extern void finish_compound_stmt               (tree);
 extern tree finish_asm_stmt                    (int, tree, tree, tree, tree,
-                                                tree);
+                                                tree, bool);
 extern tree finish_label_stmt                  (tree);
 extern void finish_label_decl                  (tree);
 extern cp_expr finish_parenthesized_expr       (cp_expr);
index c2fa60b4aadb8430c1ae8507be20b7c1bd777ca0..1f80a3c60d066a13e805798c1d6f55c30c06590c 100644 (file)
@@ -18789,22 +18789,35 @@ cp_parser_using_directive (cp_parser* parser)
 
 /* Parse an asm-definition.
 
+  asm-qualifier:
+    volatile
+    inline
+    goto
+
+  asm-qualifier-list:
+    asm-qualifier
+    asm-qualifier-list asm-qualifier
+
    asm-definition:
      asm ( string-literal ) ;
 
    GNU Extension:
 
    asm-definition:
-     asm volatile [opt] ( string-literal ) ;
-     asm volatile [opt] ( string-literal : asm-operand-list [opt] ) ;
-     asm volatile [opt] ( string-literal : asm-operand-list [opt]
-                         : asm-operand-list [opt] ) ;
-     asm volatile [opt] ( string-literal : asm-operand-list [opt]
-                         : asm-operand-list [opt]
+     asm asm-qualifier-list [opt] ( string-literal ) ;
+     asm asm-qualifier-list [opt] ( string-literal : asm-operand-list [opt] ) ;
+     asm asm-qualifier-list [opt] ( string-literal : asm-operand-list [opt]
+                                   : asm-operand-list [opt] ) ;
+     asm asm-qualifier-list [opt] ( string-literal : asm-operand-list [opt]
+                                   : asm-operand-list [opt]
                          : asm-clobber-list [opt] ) ;
-     asm volatile [opt] goto ( string-literal : : asm-operand-list [opt]
-                              : asm-clobber-list [opt]
-                              : asm-goto-list ) ;  */
+     asm asm-qualifier-list [opt] ( string-literal : : asm-operand-list [opt]
+                                   : asm-clobber-list [opt]
+                                   : asm-goto-list ) ;
+
+  The form with asm-goto-list is valid if and only if the asm-qualifier-list
+  contains goto, and is the only allowed form in that case.  No duplicates are
+  allowed in an asm-qualifier-list.  */
 
 static void
 cp_parser_asm_definition (cp_parser* parser)
@@ -18815,11 +18828,9 @@ cp_parser_asm_definition (cp_parser* parser)
   tree clobbers = NULL_TREE;
   tree labels = NULL_TREE;
   tree asm_stmt;
-  bool volatile_p = false;
   bool extended_p = false;
   bool invalid_inputs_p = false;
   bool invalid_outputs_p = false;
-  bool goto_p = false;
   required_token missing = RT_NONE;
 
   /* Look for the `asm' keyword.  */
@@ -18832,24 +18843,67 @@ cp_parser_asm_definition (cp_parser* parser)
       cp_function_chain->invalid_constexpr = true;
     }
 
-  /* See if the next token is `volatile'.  */
-  if (cp_parser_allow_gnu_extensions_p (parser)
-      && cp_lexer_next_token_is_keyword (parser->lexer, RID_VOLATILE))
-    {
-      /* Remember that we saw the `volatile' keyword.  */
-      volatile_p = true;
-      /* Consume the token.  */
-      cp_lexer_consume_token (parser->lexer);
-    }
-  if (cp_parser_allow_gnu_extensions_p (parser)
-      && parser->in_function_body
-      && cp_lexer_next_token_is_keyword (parser->lexer, RID_GOTO))
-    {
-      /* Remember that we saw the `goto' keyword.  */
-      goto_p = true;
-      /* Consume the token.  */
-      cp_lexer_consume_token (parser->lexer);
-    }
+  /* Handle the asm-qualifier-list.  */
+  location_t volatile_loc = UNKNOWN_LOCATION;
+  location_t inline_loc = UNKNOWN_LOCATION;
+  location_t goto_loc = UNKNOWN_LOCATION;
+
+  if (cp_parser_allow_gnu_extensions_p (parser) && parser->in_function_body)
+    for (;;)
+      {
+       cp_token *token = cp_lexer_peek_token (parser->lexer);
+       location_t loc = token->location;
+       switch (cp_lexer_peek_token (parser->lexer)->keyword)
+         {
+         case RID_VOLATILE:
+           if (volatile_loc)
+             {
+               error_at (loc, "duplicate asm qualifier %qT", token->u.value);
+               inform (volatile_loc, "first seen here");
+             }
+           else
+             volatile_loc = loc;
+           cp_lexer_consume_token (parser->lexer);
+           continue;
+
+         case RID_INLINE:
+           if (inline_loc)
+             {
+               error_at (loc, "duplicate asm qualifier %qT", token->u.value);
+               inform (inline_loc, "first seen here");
+             }
+           else
+             inline_loc = loc;
+           cp_lexer_consume_token (parser->lexer);
+           continue;
+
+         case RID_GOTO:
+           if (goto_loc)
+             {
+               error_at (loc, "duplicate asm qualifier %qT", token->u.value);
+               inform (goto_loc, "first seen here");
+             }
+           else
+             goto_loc = loc;
+           cp_lexer_consume_token (parser->lexer);
+           continue;
+
+         case RID_CONST:
+         case RID_RESTRICT:
+           error_at (loc, "%qT is not an asm qualifier", token->u.value);
+           cp_lexer_consume_token (parser->lexer);
+           continue;
+
+         default:
+           break;
+         }
+       break;
+      }
+
+  bool volatile_p = (volatile_loc != UNKNOWN_LOCATION);
+  bool inline_p = (inline_loc != UNKNOWN_LOCATION);
+  bool goto_p = (goto_loc != UNKNOWN_LOCATION);
+
   /* Look for the opening `('.  */
   if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
     return;
@@ -18941,8 +18995,7 @@ cp_parser_asm_definition (cp_parser* parser)
                                             CPP_CLOSE_PAREN))
            clobbers = cp_parser_asm_clobber_list (parser);
        }
-      else if (goto_p
-              && cp_lexer_next_token_is (parser->lexer, CPP_SCOPE))
+      else if (goto_p && cp_lexer_next_token_is (parser->lexer, CPP_SCOPE))
        /* The labels are coming next.  */
        labels_p = true;
 
@@ -18976,7 +19029,7 @@ cp_parser_asm_definition (cp_parser* parser)
       if (parser->in_function_body)
        {
          asm_stmt = finish_asm_stmt (volatile_p, string, outputs,
-                                     inputs, clobbers, labels);
+                                     inputs, clobbers, labels, inline_p);
          /* If the extended syntax was not used, mark the ASM_EXPR.  */
          if (!extended_p)
            {
index 71077a3b049847ccc6a67653e0da3027fa9cc8b2..2df7402c905bb55e84a6c05dd79fc8227d3cef89 100644 (file)
@@ -16159,7 +16159,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
        tree labels = tsubst_copy_asm_operands (ASM_LABELS (t), args,
                                                complain, in_decl);
        tmp = finish_asm_stmt (ASM_VOLATILE_P (t), string, outputs, inputs,
-                              clobbers, labels);
+                              clobbers, labels, ASM_INLINE_P (t));
        tree asm_expr = tmp;
        if (TREE_CODE (asm_expr) == CLEANUP_POINT_EXPR)
          asm_expr = TREE_OPERAND (asm_expr, 0);
index 34ca72e10a0ac71c77146607da0c066a0094ff9c..785fc4a7b380f141d63458cc06d700f5bdde79c7 100644 (file)
@@ -1429,11 +1429,11 @@ finish_compound_stmt (tree stmt)
 /* Finish an asm-statement, whose components are a STRING, some
    OUTPUT_OPERANDS, some INPUT_OPERANDS, some CLOBBERS and some
    LABELS.  Also note whether the asm-statement should be
-   considered volatile.  */
+   considered volatile, and whether it is asm inline.  */
 
 tree
 finish_asm_stmt (int volatile_p, tree string, tree output_operands,
-                tree input_operands, tree clobbers, tree labels)
+                tree input_operands, tree clobbers, tree labels, bool inline_p)
 {
   tree r;
   tree t;
@@ -1587,6 +1587,7 @@ finish_asm_stmt (int volatile_p, tree string, tree output_operands,
                  output_operands, input_operands,
                  clobbers, labels);
   ASM_VOLATILE_P (r) = volatile_p || noutputs == 0;
+  ASM_INLINE_P (r) = inline_p;
   r = maybe_cleanup_point_expr_void (r);
   return add_stmt (r);
 }
index d1ba85e709a45e73c24bbb736b9a313b264bc0b1..dbcf13f862bcdfdc5f2231d5291b0235b71a791d 100644 (file)
@@ -7710,7 +7710,7 @@ for a C symbol, or to place a C variable in a specific register.
 A basic @code{asm} statement has the following syntax:
 
 @example
-asm @r{[} volatile @r{]} ( @var{AssemblerInstructions} )
+asm @var{asm-qualifiers} ( @var{AssemblerInstructions} )
 @end example
 
 The @code{asm} keyword is a GNU extension.
@@ -7723,6 +7723,10 @@ various @option{-std} options, use @code{__asm__} instead of
 @item volatile
 The optional @code{volatile} qualifier has no effect. 
 All basic @code{asm} blocks are implicitly volatile.
+
+@item inline
+If you use the @code{inline} qualifier, then for inlining purposes the size
+of the asm is taken as the smallest size possible (@pxref{Size of an asm}).
 @end table
 
 @subsubheading Parameters
@@ -7838,17 +7842,19 @@ Extended @code{asm} syntax uses colons (@samp{:}) to delimit
 the operand parameters after the assembler template:
 
 @example
-asm @r{[}volatile@r{]} ( @var{AssemblerTemplate} 
+asm @var{asm-qualifiers} ( @var{AssemblerTemplate} 
                  : @var{OutputOperands} 
                  @r{[} : @var{InputOperands}
                  @r{[} : @var{Clobbers} @r{]} @r{]})
 
-asm @r{[}volatile@r{]} goto ( @var{AssemblerTemplate} 
+asm @var{asm-qualifiers} ( @var{AssemblerTemplate} 
                       : 
                       : @var{InputOperands}
                       : @var{Clobbers}
                       : @var{GotoLabels})
 @end example
+where in the last form, @var{asm-qualifiers} contains @code{goto} (and in the
+first form, not).
 
 The @code{asm} keyword is a GNU extension.
 When writing code that can be compiled with @option{-ansi} and the
@@ -7864,6 +7870,10 @@ values to produce output values. However, your @code{asm} statements may
 also produce side effects. If so, you may need to use the @code{volatile} 
 qualifier to disable certain optimizations. @xref{Volatile}.
 
+@item inline
+If you use the @code{inline} qualifier, then for inlining purposes the size
+of the asm is taken as the smallest size possible (@pxref{Size of an asm}).
+
 @item goto
 This qualifier informs the compiler that the @code{asm} statement may 
 perform a jump to one of the labels listed in the @var{GotoLabels}.
@@ -9146,7 +9156,7 @@ does this by counting the number of instructions in the pattern of the
 @code{asm} and multiplying that by the length of the longest
 instruction supported by that processor.  (When working out the number
 of instructions, it assumes that any occurrence of a newline or of
-whatever statement separator character is supported by the assembler --
+whatever statement separator character is supported by the assembler ---
 typically @samp{;} --- indicates the end of an instruction.)
 
 Normally, GCC's estimate is adequate to ensure that correct
@@ -9157,6 +9167,11 @@ space in the object file than is needed for a single instruction.
 If this happens then the assembler may produce a diagnostic saying that
 a label is unreachable.
 
+@cindex @code{asm inline}
+This size is also used for inlining decisions.  If you use @code{asm inline}
+instead of just @code{asm}, then for inlining purposes the size of the asm
+is taken as the minimum size, ignoring how many instructions GCC thinks it is.
+
 @node Alternate Keywords
 @section Alternate Keywords
 @cindex alternate keywords
index 49cc80c57d71ff2c4ceb02a71bf733763a74851f..79e9c8ce15d5e4a663b9936179e101d132ca5802 100644 (file)
@@ -1989,6 +1989,8 @@ dump_gimple_asm (pretty_printer *buffer, gasm *gs, int spc, int flags)
       pp_string (buffer, "__asm__");
       if (gimple_asm_volatile_p (gs))
        pp_string (buffer, " __volatile__");
+      if (gimple_asm_inline_p (gs))
+       pp_string (buffer, " __inline__");
       if (gimple_asm_nlabels (gs))
        pp_string (buffer, " goto");
       pp_string (buffer, "(\"");
index 460011c87f10fbec1930c7c662b069ad00e47941..7e9e0bd38a3ba1a9de9f246b3b97af70745e5f7a 100644 (file)
@@ -136,6 +136,7 @@ enum gimple_rhs_class
 enum gf_mask {
     GF_ASM_INPUT               = 1 << 0,
     GF_ASM_VOLATILE            = 1 << 1,
+    GF_ASM_INLINE              = 1 << 2,
     GF_CALL_FROM_THUNK         = 1 << 0,
     GF_CALL_RETURN_SLOT_OPT    = 1 << 1,
     GF_CALL_TAILCALL           = 1 << 2,
@@ -3909,7 +3910,7 @@ gimple_asm_string (const gasm *asm_stmt)
 }
 
 
-/* Return true ASM_STMT ASM_STMT is an asm statement marked volatile.  */
+/* Return true if ASM_STMT is marked volatile.  */
 
 static inline bool
 gimple_asm_volatile_p (const gasm *asm_stmt)
@@ -3918,7 +3919,7 @@ gimple_asm_volatile_p (const gasm *asm_stmt)
 }
 
 
-/* If VOLATLE_P is true, mark asm statement ASM_STMT as volatile.  */
+/* If VOLATILE_P is true, mark asm statement ASM_STMT as volatile.  */
 
 static inline void
 gimple_asm_set_volatile (gasm *asm_stmt, bool volatile_p)
@@ -3930,6 +3931,27 @@ gimple_asm_set_volatile (gasm *asm_stmt, bool volatile_p)
 }
 
 
+/* Return true if ASM_STMT is marked inline.  */
+
+static inline bool
+gimple_asm_inline_p (const gasm *asm_stmt)
+{
+  return (asm_stmt->subcode & GF_ASM_INLINE) != 0;
+}
+
+
+/* If INLINE_P is true, mark asm statement ASM_STMT as inline.  */
+
+static inline void
+gimple_asm_set_inline (gasm *asm_stmt, bool inline_p)
+{
+  if (inline_p)
+    asm_stmt->subcode |= GF_ASM_INLINE;
+  else
+    asm_stmt->subcode &= ~GF_ASM_INLINE;
+}
+
+
 /* If INPUT_P is true, mark asm ASM_STMT as an ASM_INPUT.  */
 
 static inline void
index b6732e7a2a1af71e8c754dcd8bdf6b67b22db2f3..818f0abd2f921d38da6451b34531c8e7ae56007e 100644 (file)
@@ -6206,6 +6206,7 @@ gimplify_asm_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
 
       gimple_asm_set_volatile (stmt, ASM_VOLATILE_P (expr) || noutputs == 0);
       gimple_asm_set_input (stmt, ASM_INPUT_P (expr));
+      gimple_asm_set_inline (stmt, ASM_INLINE_P (expr));
 
       gimplify_seq_add_stmt (pre_p, stmt);
     }
index b40dd8653b4d5b2a3e482e3b124bbd995c0472be..9a1ca00392d3dd6dd5e508ff75707ec4bbb7fe94 100644 (file)
@@ -994,6 +994,9 @@ func_checker::compare_gimple_asm (const gasm *g1, const gasm *g2)
   if (gimple_asm_input_p (g1) != gimple_asm_input_p (g2))
     return false;
 
+  if (gimple_asm_inline_p (g1) != gimple_asm_inline_p (g2))
+    return false;
+
   if (gimple_asm_ninputs (g1) != gimple_asm_ninputs (g2))
     return false;
 
index 99826ff696b67ac3da87fc51af4c69c281bd5f83..4d42c10dc0fbfab8b3453f60f89ef914143e4a70 100644 (file)
@@ -1,3 +1,37 @@
+2018-01-02  Segher Boessenkool  <segher@kernel.crashing.org>
+
+       Backport from trunk
+       2018-12-06  Segher Boessenkool  <segher@kernel.crashing.org>
+
+       PR inline-asm/55681
+       * gcc.dg/asm-qual-1.c: Test that "const" and "restrict" are refused.
+       * gcc.dg/asm-qual-2.c: New test, test that asm-qualifiers are allowed
+       in any order, but that duplicates are not allowed.
+
+       Backport from trunk
+       2018-12-06  Segher Boessenkool  <segher@kernel.crashing.org>
+
+       * c-c++-common/torture/asm-inline.c: New testcase.
+       * gcc.dg/asm-qual-2.c: Test asm inline, too.
+
+       Backport from trunk
+       2018-12-19  Segher Boessenkool  <segher@kernel.crashing.org>
+
+       * g++.dg/asm-qual-1.C: New testcase.
+       * g++.dg/asm-qual-2.C: New testcase.
+       * gcc.dg/asm-qual-1.c: Update.
+
+       Backport from trunk
+       2018-12-19  Segher Boessenkool  <segher@kernel.crashing.org>
+
+       * g++.dg/asm-qual-3.C: New testcase.
+       * gcc.dg/asm-qual-3.c: New testcase.
+
+       And extra for the backport
+       2019-01-02  Segher Boessenkool  <segher@kernel.crashing.org>
+
+       * gcc.dg/asm-qual-1.c: Adjust.
+
 2018-12-30  Dominique d'Humieres  <dominiq@gcc.gnu.org>
 
        PR tree-optimization/68356
diff --git a/gcc/testsuite/c-c++-common/torture/asm-inline.c b/gcc/testsuite/c-c++-common/torture/asm-inline.c
new file mode 100644 (file)
index 0000000..dea8965
--- /dev/null
@@ -0,0 +1,53 @@
+/* { dg-do compile } */
+/* -O0 does no inlining, and -O3 does it too aggressively for this test:  */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O3" } { "" } }
+/* The normal asm is not inlined:  */
+/* { dg-final { scan-assembler-times "w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w" 2 } } */
+/* But the asm inline is inlined:  */
+/* { dg-final { scan-assembler-times "x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x" 8 } } */
+
+static void f(void)
+{
+  asm ("w\nw\nw\nw\nw\nw\nw\nw\nw\nw\nw\nw\nw\nw\nw\n"
+       "w\nw\nw\nw\nw\nw\nw\nw\nw\nw\nw\nw\nw\nw\nw");
+}
+
+int f0(void) { f(); return 0; }
+int f1(void) { f(); return 1; }
+int f2(void) { f(); return 2; }
+int f3(void) { f(); return 3; }
+
+static void fg(void)
+{
+  asm goto("w\nw\nw\nw\nw\nw\nw\nw\nw\nw\nw\nw\nw\nw\nw\n"
+          "w\nw\nw\nw\nw\nw\nw\nw\nw\nw\nw\nw\nw\nw\nw" :::: q);
+  q: ;
+}
+
+int fg0(void) { fg(); return 0; }
+int fg1(void) { fg(); return 1; }
+int fg2(void) { fg(); return 2; }
+int fg3(void) { fg(); return 3; }
+
+static void g(void)
+{
+  asm inline("x\nx\nx\nx\nx\nx\nx\nx\nx\nx\nx\nx\nx\nx\nx\n"
+            "x\nx\nx\nx\nx\nx\nx\nx\nx\nx\nx\nx\nx\nx\nx");
+}
+
+int g0(void) { g(); return 0; }
+int g1(void) { g(); return 1; }
+int g2(void) { g(); return 2; }
+int g3(void) { g(); return 3; }
+
+static void gg(void)
+{
+  asm inline goto("x\nx\nx\nx\nx\nx\nx\nx\nx\nx\nx\nx\nx\nx\nx\n"
+                 "x\nx\nx\nx\nx\nx\nx\nx\nx\nx\nx\nx\nx\nx\nx" :::: q);
+  q: ;
+}
+
+int gg0(void) { gg(); return 0; }
+int gg1(void) { gg(); return 1; }
+int gg2(void) { gg(); return 2; }
+int gg3(void) { gg(); return 3; }
diff --git a/gcc/testsuite/g++.dg/asm-qual-1.C b/gcc/testsuite/g++.dg/asm-qual-1.C
new file mode 100644 (file)
index 0000000..3fba592
--- /dev/null
@@ -0,0 +1,13 @@
+// Test that qualifiers other than volatile are disallowed on asm.
+// { dg-do compile }
+// { dg-options "-std=gnu++98" }
+
+void
+f ()
+{
+  asm volatile ("");
+
+  asm const (""); // { dg-error {'const' is not an asm qualifier} }
+
+  asm __restrict (""); // { dg-error {'__restrict' is not an asm qualifier} }
+}
diff --git a/gcc/testsuite/g++.dg/asm-qual-2.C b/gcc/testsuite/g++.dg/asm-qual-2.C
new file mode 100644 (file)
index 0000000..52968bd
--- /dev/null
@@ -0,0 +1,46 @@
+// Test that qualifiers on asm are allowed in any order.
+// { dg-do compile }
+// { dg-options "-std=c++98" }
+
+void
+f ()
+{
+  asm volatile goto ("" :::: lab);
+  asm volatile inline ("" :::);
+  asm inline volatile ("" :::);
+  asm inline goto ("" :::: lab);
+  asm goto volatile ("" :::: lab);
+  asm goto inline ("" :::: lab);
+
+  asm volatile inline goto ("" :::: lab);
+  asm volatile goto inline ("" :::: lab);
+  asm inline volatile goto ("" :::: lab);
+  asm inline goto volatile ("" :::: lab);
+  asm goto volatile inline ("" :::: lab);
+  asm goto inline volatile ("" :::: lab);
+
+  /* Duplicates are not allowed.  */
+  asm goto volatile volatile ("" :::: lab);  /* { dg-error "" } */
+  asm volatile goto volatile ("" :::: lab);  /* { dg-error "" } */
+  asm volatile volatile goto ("" :::: lab);  /* { dg-error "" } */
+  asm goto goto volatile ("" :::: lab);  /* { dg-error "" } */
+  asm goto volatile goto ("" :::: lab);  /* { dg-error "" } */
+  asm volatile goto goto ("" :::: lab);  /* { dg-error "" } */
+
+  asm inline volatile volatile ("" :::);  /* { dg-error "" } */
+  asm volatile inline volatile ("" :::);  /* { dg-error "" } */
+  asm volatile volatile inline ("" :::);  /* { dg-error "" } */
+  asm inline inline volatile ("" :::);  /* { dg-error "" } */
+  asm inline volatile inline ("" :::);  /* { dg-error "" } */
+  asm volatile inline inline ("" :::);  /* { dg-error "" } */
+
+  asm goto inline inline ("" :::: lab);  /* { dg-error "" } */
+  asm inline goto inline ("" :::: lab);  /* { dg-error "" } */
+  asm inline inline goto ("" :::: lab);  /* { dg-error "" } */
+  asm goto goto inline ("" :::: lab);  /* { dg-error "" } */
+  asm goto inline goto ("" :::: lab);  /* { dg-error "" } */
+  asm inline goto goto ("" :::: lab);  /* { dg-error "" } */
+
+lab:
+  ;
+}
diff --git a/gcc/testsuite/g++.dg/asm-qual-3.C b/gcc/testsuite/g++.dg/asm-qual-3.C
new file mode 100644 (file)
index 0000000..95c9b57
--- /dev/null
@@ -0,0 +1,12 @@
+// Test that asm-qualifiers are not allowed on toplevel asm.
+// { dg-do compile }
+// { dg-options "-std=gnu++98" }
+
+asm const ("");    // { dg-error {expected '\(' before 'const'} }
+asm volatile (""); // { dg-error {expected '\(' before 'volatile'} }
+asm restrict (""); // { dg-error {expected '\(' before 'restrict'} }
+asm inline ("");   // { dg-error {expected '\(' before 'inline'} }
+asm goto ("");     // { dg-error {expected '\(' before 'goto'} }
+
+// There are many other things wrong with this code, so:
+// { dg-excess-errors "" }
index 5ec9a29a9108386334e5e6dc6c78f2e74a8d1222..4982a6b7f058aaecc2e832160c6f909b689904b5 100644 (file)
@@ -1,4 +1,4 @@
-/* Test that qualifiers other than volatile are ignored on asm.  */
+/* Test that qualifiers other than volatile are disallowed on asm.  */
 /* Origin: Joseph Myers <joseph@codesourcery.com> */
 /* { dg-do compile } */
 /* { dg-options "-std=gnu99" } */
@@ -7,6 +7,8 @@ void
 f (void)
 {
   asm volatile ("");
-  asm const (""); /* { dg-warning "const qualifier ignored on asm" } */
-  asm restrict (""); /* { dg-warning "restrict qualifier ignored on asm" } */
+
+  asm const (""); /* { dg-warning {'const' is not an asm qualifier} } */
+
+  asm restrict (""); /* { dg-warning {'restrict' is not an asm qualifier} } */
 }
diff --git a/gcc/testsuite/gcc.dg/asm-qual-2.c b/gcc/testsuite/gcc.dg/asm-qual-2.c
new file mode 100644 (file)
index 0000000..79135c3
--- /dev/null
@@ -0,0 +1,46 @@
+/* Test that qualifiers on asm are allowed in any order.  */
+/* { dg-do compile } */
+/* { dg-options "-std=gnu99" } */
+
+void
+f (void)
+{
+  asm volatile goto ("" :::: lab);
+  asm volatile inline ("" :::);
+  asm inline volatile ("" :::);
+  asm inline goto ("" :::: lab);
+  asm goto volatile ("" :::: lab);
+  asm goto inline ("" :::: lab);
+
+  asm volatile inline goto ("" :::: lab);
+  asm volatile goto inline ("" :::: lab);
+  asm inline volatile goto ("" :::: lab);
+  asm inline goto volatile ("" :::: lab);
+  asm goto volatile inline ("" :::: lab);
+  asm goto inline volatile ("" :::: lab);
+
+  /* Duplicates are not allowed.  */
+  asm goto volatile volatile ("" :::: lab);  /* { dg-error "" } */
+  asm volatile goto volatile ("" :::: lab);  /* { dg-error "" } */
+  asm volatile volatile goto ("" :::: lab);  /* { dg-error "" } */
+  asm goto goto volatile ("" :::: lab);  /* { dg-error "" } */
+  asm goto volatile goto ("" :::: lab);  /* { dg-error "" } */
+  asm volatile goto goto ("" :::: lab);  /* { dg-error "" } */
+
+  asm inline volatile volatile ("" :::);  /* { dg-error "" } */
+  asm volatile inline volatile ("" :::);  /* { dg-error "" } */
+  asm volatile volatile inline ("" :::);  /* { dg-error "" } */
+  asm inline inline volatile ("" :::);  /* { dg-error "" } */
+  asm inline volatile inline ("" :::);  /* { dg-error "" } */
+  asm volatile inline inline ("" :::);  /* { dg-error "" } */
+
+  asm goto inline inline ("" :::: lab);  /* { dg-error "" } */
+  asm inline goto inline ("" :::: lab);  /* { dg-error "" } */
+  asm inline inline goto ("" :::: lab);  /* { dg-error "" } */
+  asm goto goto inline ("" :::: lab);  /* { dg-error "" } */
+  asm goto inline goto ("" :::: lab);  /* { dg-error "" } */
+  asm inline goto goto ("" :::: lab);  /* { dg-error "" } */
+
+lab:
+  ;
+}
diff --git a/gcc/testsuite/gcc.dg/asm-qual-3.c b/gcc/testsuite/gcc.dg/asm-qual-3.c
new file mode 100644 (file)
index 0000000..f85d8bf
--- /dev/null
@@ -0,0 +1,9 @@
+/* Test that asm-qualifiers are not allowed on toplevel asm.  */
+/* { dg-do compile } */
+/* { dg-options "-std=gnu99" } */
+
+asm const ("");    /* { dg-error {expected '\(' before 'const'} } */
+asm volatile (""); /* { dg-error {expected '\(' before 'volatile'} } */
+asm restrict (""); /* { dg-error {expected '\(' before 'restrict'} } */
+asm inline ("");   /* { dg-error {expected '\(' before 'inline'} } */
+asm goto ("");     /* { dg-error {expected '\(' before 'goto'} } */
index a646ecb5c951869fa8bfa3af11c524414c0c6c3b..38154e384c00ec5d6a98efee01d633cbc0812ff0 100644 (file)
@@ -1138,6 +1138,9 @@ struct GTY(()) tree_base {
        OMP_CLAUSE_LINEAR_VARIABLE_STRIDE in
           OMP_CLAUSE_LINEAR
 
+       ASM_INLINE_P in
+          ASM_EXPR
+
    side_effects_flag:
 
        TREE_SIDE_EFFECTS in
index d675f66cdbf7f21dd56d71ab0e24618eef49d544..e12d2e9f5d6ae567a3126b2e7d16edd0b4edd8d2 100644 (file)
@@ -4173,6 +4173,9 @@ estimate_num_insns (gimple *stmt, eni_weights *weights)
           with very long asm statements.  */
        if (count > 1000)
          count = 1000;
+       /* If this asm is asm inline, count anything as minimum size.  */
+       if (gimple_asm_inline_p (as_a <gasm *> (stmt)))
+         count = MIN (1, count);
        return count;
       }
 
index f20b77f17e47b51dc0978a119997e60c937048ab..961dba39403de5d1cd00089932646e1a13766475 100644 (file)
@@ -1231,6 +1231,9 @@ extern void protected_set_expr_location (tree, location_t);
    ASM_OPERAND with no operands.  */
 #define ASM_INPUT_P(NODE) (ASM_EXPR_CHECK (NODE)->base.static_flag)
 #define ASM_VOLATILE_P(NODE) (ASM_EXPR_CHECK (NODE)->base.public_flag)
+/* Nonzero if we want to consider this asm as minimum length and cost
+   for inlining decisions.  */
+#define ASM_INLINE_P(NODE) (ASM_EXPR_CHECK (NODE)->base.protected_flag)
 
 /* COND_EXPR accessors.  */
 #define COND_EXPR_COND(NODE)   (TREE_OPERAND (COND_EXPR_CHECK (NODE), 0))