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

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 e6960445024ce5f0476b159d53957c4664de19a9..946fbbe560cb9144d77581d026a248a14c28615c 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-28  Thomas Schwinge  <thomas@codesourcery.com>
            Julian Brown  <julian@codesourcery.com>
 
index bfecadc61b08d3446aa539f7e82c72035d681d8f..21d64b15aefdb1c60afe9a5485103754cabb67b0 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-08-01  Jakub Jelinek  <jakub@redhat.com>
 
        PR c/85704
index 47720861d3f22ea1ec414c0f134004b355798df3..a9601699be0e0faa9273ce75ea6f77f1bc4f9d36 100644 (file)
@@ -6261,61 +6261,104 @@ c_parser_for_statement (c_parser *parser, bool ivdep, unsigned short unroll,
 }
 
 /* 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;
@@ -6390,8 +6433,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 ae1a1e60d4bf4626accf2235dff8213b3502cc5f..aa66aa27b3957d5f37e07ed0c7d4691cba889765 100644 (file)
@@ -677,8 +677,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 820591683ab80d8097fb5453767f29358156ea89..7b90b5cd2f060bf49118404757210476d3a660d4 100644 (file)
@@ -9979,9 +9979,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);
 }
@@ -9990,10 +9990,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;
@@ -10111,6 +10113,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 5687ec277c587aaa973047489d3cec73a4883357..6f21e611d3ec028f339496bfed46314c943fcbbb 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-13  Nathan Sidwell  <nathan@acm.org>
 
        PR c++/87531
index 85ba5b87e3bd68036eb6c2a8aefa486d130829b4..0f24b4fc94581dff5745246d5e9e502bcca29c27 100644 (file)
@@ -6897,7 +6897,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 9907180d3cbd379c47c2a70130461035f4224d10..afc7b96db19ca1965eb9794ce24b40337f7e5f65 100644 (file)
@@ -19067,22 +19067,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)
@@ -19093,11 +19106,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.  */
@@ -19110,24 +19121,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;
@@ -19219,8 +19273,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;
 
@@ -19254,7 +19307,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 e9a9ac9425529cc4db728ae61084791784f6c8bd..446f4fbc65846449243be30c76b7b003c5143804 100644 (file)
@@ -16990,7 +16990,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 1744ec0ab5d2e54030e71dd49a18b909a8589d64..1f6c9be6d6fda6691665b2794173702a5f6ed0fa 100644 (file)
@@ -1461,11 +1461,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;
@@ -1619,6 +1619,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 afde889bec702ce614994f476479fd243fa49b86..4ff37c49ce2a401628205dae7283dc358e77b123 100644 (file)
@@ -8147,7 +8147,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.
@@ -8160,6 +8160,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
@@ -8275,17 +8279,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
@@ -8301,6 +8307,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}.
@@ -9712,7 +9722,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
@@ -9723,6 +9733,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 6695526f3702dbf7aa286b430e7042de6b159133..487770f8488a8811caef2b4a621b00f8df32301b 100644 (file)
@@ -2040,6 +2040,8 @@ dump_gimple_asm (pretty_printer *buffer, gasm *gs, int spc, dump_flags_t 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 265e3e24398cc6129c6e2b9f2c475174cfbf1970..224463b33d07d18098da238353369bbba3e9c13c 100644 (file)
@@ -137,6 +137,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,
@@ -3925,7 +3926,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)
@@ -3934,7 +3935,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)
@@ -3946,6 +3947,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 8f1328691cf58dd362c07f7531427b0f980f0e76..3adf2cb5df56df3668aa03207030606e8c136789 100644 (file)
@@ -6360,6 +6360,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 161080c77bc72785cd0ae0724839630ccabd2323..37b9fe73b0acac7bfa7367bf46573ca9c72ee329 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 abd97d331501ee5adf782ef1d30034efe04dc4f4..4c00eb467d4f153490974344cac8501355ec5585 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>
 
        * g++.dg/abi/key2.C: Silence the [-Wreturn-type] warning.
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 356330a5b0e7bdd8e955a8673f7bf28a0755c4ec..84f75e66ca99ee0ad8796392e4b70da08b2fdf79 100644 (file)
@@ -1161,6 +1161,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 7555dce225533c59b9b958e2e1c82e8968a5d5a1..324c168292122864196383b7bf7e3caa84c8d50e 100644 (file)
@@ -4149,6 +4149,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 MAX (1, count);
       }
 
index 8e703140811fada0ea7f0bdf645a4d7ca9fab446..324ef5b45e74f20d7b8bcf6de60486bcd7357799 100644 (file)
@@ -1263,6 +1263,9 @@ extern tree maybe_wrap_with_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))
This page took 0.231274 seconds and 5 git commands to generate.