This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

C front end asm() syntax refactor


Eric's working on a patch to address some problems with -fexec-charset
(it applies the character set translation to strings that should not
be translated, such as the strings in asm() expressions).  This
requires contextual information about what a given string constant is
going to be used for.  This patch refactors the asm() grammar
productions to make that easier.

A side effect is that arbitrary expressions are no longer
syntactically valid inside asm().  Anything other than a bare string
constant was being rejected by semantic processing, anyway, so the
extra flexibility gains nothing.

Bootstrapped i686-linux, applied mainline.  The entire patch series
that this is part of may be appropriate for 3.4 branch at some point.

zw

        * c-parse.in (maybe_type_qual): Delete.
        (maybe_volatile, simple_asm_expr, asmdef, asm_stmt)
        (asm_argument): New grammar rules.
        (extdef_1): Use asmdef.
        (maybeasm): Move down with other asm rules; use simple_asm_expr.
        (xexpr): Move up with other expression rules.
        (stmt): Use asm_stmt.

        * c-typeck.c (build_asm_expr): New function - body mostly
        pulled from build_asm_stmt.
        (build_asm_stmt): Just handle tacking on the volatile qualifier.
        * c-tree.h (build_asm_expr, build_asm_stmt): Update prototypes.

===================================================================
Index: c-parse.in
--- c-parse.in	8 Feb 2004 20:55:27 -0000	1.199
+++ c-parse.in	12 Feb 2004 19:04:24 -0000
@@ -200,9 +200,9 @@ do {									\
 %type <ttype> typespec_reserved_nonattr typespec_reserved_attr
 %type <ttype> typespec_nonreserved_nonattr
 
-%type <ttype> scspec SCSPEC STATIC TYPESPEC TYPE_QUAL maybe_type_qual
-%type <ttype> initdecls notype_initdecls initdcl notype_initdcl
-%type <ttype> init maybeasm
+%type <ttype> scspec SCSPEC STATIC TYPESPEC TYPE_QUAL maybe_volatile
+%type <ttype> initdecls notype_initdecls initdcl notype_initdcl init
+%type <ttype> simple_asm_expr maybeasm asmdef asm_stmt asm_argument
 %type <ttype> asm_operands nonnull_asm_operands asm_operand asm_clobbers
 %type <ttype> maybe_attribute attributes attribute attribute_list attrib
 %type <ttype> any_word
@@ -375,19 +375,12 @@ extdef:
 extdef_1:
 	fndef
 	| datadef
+	| asmdef
+	| extension extdef
+		{ RESTORE_EXT_FLAGS ($1); }
 @@ifobjc
 	| objcdef
 @@end_ifobjc
-	| ASM_KEYWORD '(' expr ')' ';'
-		{ STRIP_NOPS ($3);
-		  if ((TREE_CODE ($3) == ADDR_EXPR
-		       && TREE_CODE (TREE_OPERAND ($3, 0)) == STRING_CST)
-		      || TREE_CODE ($3) == STRING_CST)
-		    assemble_asm ($3);
-		  else
-		    error ("argument of `asm' is not a constant string"); }
-	| extension extdef
-		{ RESTORE_EXT_FLAGS ($1); }
 	;
 
 datadef:
@@ -1392,13 +1385,6 @@ notype_initdecls:
 	| notype_initdecls ',' maybe_resetattrs notype_initdcl
 	;
 
-maybeasm:
-	  /* empty */
-		{ $$ = NULL_TREE; }
-	| ASM_KEYWORD '(' STRING ')'
-		{ $$ = $3; }
-	;
-
 initdcl:
 	  declarator maybeasm maybe_attribute '='
 		{ $<ttype>$ = start_decl ($1, current_declspecs, 1,
@@ -2346,6 +2332,12 @@ for_init_stmt:
 		{ check_for_loop_decls (); }
 	;
 
+xexpr:
+	/* empty */
+		{ $$ = NULL_TREE; }
+	| expr
+	;
+
 /* Parse a single real statement, not including any labels.  */
 stmt:
 	  compstmt
@@ -2381,23 +2373,7 @@ stmt:
 	| RETURN expr ';'
                 { stmt_count++;
 		  $$ = c_expand_return ($2); }
-	| ASM_KEYWORD maybe_type_qual '(' expr ')' ';'
-		{ stmt_count++;
-		  $$ = simple_asm_stmt ($4); }
-	/* This is the case with just output operands.  */
-	| ASM_KEYWORD maybe_type_qual '(' expr ':' asm_operands ')' ';'
-		{ stmt_count++;
-		  $$ = build_asm_stmt ($2, $4, $6, NULL_TREE, NULL_TREE); }
-	/* This is the case with input operands as well.  */
-	| ASM_KEYWORD maybe_type_qual '(' expr ':' asm_operands ':'
-	  asm_operands ')' ';'
-		{ stmt_count++;
-		  $$ = build_asm_stmt ($2, $4, $6, $8, NULL_TREE); }
-	/* This is the case with clobbered registers as well.  */
-	| ASM_KEYWORD maybe_type_qual '(' expr ':' asm_operands ':'
-	  asm_operands ':' asm_clobbers ')' ';'
-		{ stmt_count++;
-		  $$ = build_asm_stmt ($2, $4, $6, $8, $10); }
+	| asm_stmt
 	| GOTO identifier ';'
 		{ tree decl;
 		  stmt_count++;
@@ -2499,19 +2475,65 @@ label:	  CASE expr_no_commas ':'
 		}
 	;
 
-/* Either a type-qualifier or nothing.  First thing in an `asm' statement.  */
+/* Asm expressions and statements */
 
-maybe_type_qual:
-	/* empty */
+/* simple_asm_expr is used in restricted contexts, where a full
+   expression with inputs and outputs does not make sense.  */
+simple_asm_expr:
+	ASM_KEYWORD '(' STRING ')'
+		{ $$ = $3; }
+	;
+
+/* maybeasm: used for assembly names for declarations */
+maybeasm:
+	  /* empty */
 		{ $$ = NULL_TREE; }
-	| TYPE_QUAL
-		{ }
+	| simple_asm_expr
 	;
 
-xexpr:
+/* asmdef: asm() outside a function body.  */
+asmdef:
+	simple_asm_expr ';'
+		{ assemble_asm ($1); }
+	;
+
+/* Full-blown asm statement with inputs, outputs, clobbers, and
+   volatile tag allowed.  */
+asm_stmt:
+	ASM_KEYWORD maybe_volatile '(' asm_argument ')' ';'
+		{ stmt_count++;
+		  $$ = build_asm_stmt ($2, $4); }
+	;
+
+asm_argument:
+	/* no operands */
+	STRING
+		{ $$ = build_asm_expr ($1, 0, 0, 0, true); }
+	/* output operands */
+	| STRING ':' asm_operands
+		{ $$ = build_asm_expr ($1, $3, 0, 0, false); }
+	/* output and input operands */
+	| STRING ':' asm_operands ':' asm_operands
+		{ $$ = build_asm_expr ($1, $3, $5, 0, false); }
+	/* output and input operands and clobbers */
+	| STRING ':' asm_operands ':' asm_operands ':' asm_clobbers
+		{ $$ = build_asm_expr ($1, $3, $5, $7, false); }
+	;
+
+/* Either 'volatile' or nothing.  First thing in an `asm' statement.  */
+
+maybe_volatile:
 	/* empty */
-		{ $$ = NULL_TREE; }
-	| expr
+		{ $$ = 0; }
+	| TYPE_QUAL
+		{ if ($1 != ridpointers[RID_VOLATILE])
+		    {
+		      warning ("%E qualifier ignored on asm", $1);
+		      $$ = 0;
+		    }
+		  else
+		    $$ = $1;
+		}
 	;
 
 /* These are the operands other than the first string and colon
===================================================================
Index: c-tree.h
--- c-tree.h	4 Feb 2004 19:15:16 -0000	1.138
+++ c-tree.h	12 Feb 2004 19:04:24 -0000
@@ -291,8 +291,8 @@ extern void pedwarn_c90 (const char *, .
 extern void pedwarn_c99 (const char *, ...) ATTRIBUTE_PRINTF_1;
 extern tree c_start_case (tree);
 extern void c_finish_case (void);
-extern tree simple_asm_stmt (tree);
-extern tree build_asm_stmt (tree, tree, tree, tree, tree);
+extern tree build_asm_expr (tree, tree, tree, tree, bool);
+extern tree build_asm_stmt (tree, tree);
 extern tree c_convert_parm_for_inlining (tree, tree, tree, int);
 
 /* Set to 0 at beginning of a function definition, set to 1 if
===================================================================
Index: c-typeck.c
--- c-typeck.c	5 Feb 2004 21:56:31 -0000	1.276
+++ c-typeck.c	12 Feb 2004 19:04:24 -0000
@@ -6002,52 +6002,28 @@ process_init_element (tree value)
   constructor_range_stack = 0;
 }
 
-/* Build a simple asm-statement, from one string literal.  */
+/* Build a complete asm-statement, whose components are a CV_QUALIFIER
+   (guaranteed to be 'volatile' or null) and ARGS (represented using
+   an ASM_STMT node).  */
 tree
-simple_asm_stmt (tree expr)
+build_asm_stmt (tree cv_qualifier, tree args)
 {
-  STRIP_NOPS (expr);
-
-  if (TREE_CODE (expr) == ADDR_EXPR)
-    expr = TREE_OPERAND (expr, 0);
-
-  if (TREE_CODE (expr) == STRING_CST)
-    {
-      tree stmt;
-
-      /* Simple asm statements are treated as volatile.  */
-      stmt = add_stmt (build_stmt (ASM_STMT, ridpointers[(int) RID_VOLATILE],
-				   expr, NULL_TREE, NULL_TREE, NULL_TREE));
-      ASM_INPUT_P (stmt) = 1;
-      return stmt;
-    }
-
-  error ("argument of `asm' is not a constant string");
-  return NULL_TREE;
+  if (!TREE_OPERAND (args, 0))
+    TREE_OPERAND (args, 0) = cv_qualifier;
+  return add_stmt (args);
 }
 
-/* Build an asm-statement, whose components are a CV_QUALIFIER, a
-   STRING, some OUTPUTS, some INPUTS, and some CLOBBERS.  */
-
+/* Build an asm-expr, whose components are a STRING, some OUTPUTS,
+   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_STMT node to represent this.  */
 tree
-build_asm_stmt (tree cv_qualifier, tree string, tree outputs, tree inputs,
-		tree clobbers)
+build_asm_expr (tree string, tree outputs, tree inputs, tree clobbers,
+		bool simple)
 {
   tree tail;
-
-  if (TREE_CODE (string) != STRING_CST)
-    {
-      error ("asm template is not a string constant");
-      return NULL_TREE;
-    }
-
-  if (cv_qualifier != NULL_TREE
-      && cv_qualifier != ridpointers[(int) RID_VOLATILE])
-    {
-      warning ("%s qualifier ignored on asm",
-	       IDENTIFIER_POINTER (cv_qualifier));
-      cv_qualifier = NULL_TREE;
-    }
+  tree args;
 
   /* We can remove output conversions that change the type,
      but not the mode.  */
@@ -6086,8 +6062,15 @@ build_asm_stmt (tree cv_qualifier, tree 
   for (tail = inputs; tail; tail = TREE_CHAIN (tail))
     TREE_VALUE (tail) = default_function_array_conversion (TREE_VALUE (tail));
 
-  return add_stmt (build_stmt (ASM_STMT, cv_qualifier, string,
-			       outputs, inputs, clobbers));
+  args = build_stmt (ASM_STMT, 0, string, outputs, inputs, clobbers);
+
+  /* Simple asm statements are treated as volatile.  */
+  if (simple)
+    {
+      TREE_OPERAND (args, 0) = ridpointers[RID_VOLATILE];
+      ASM_INPUT_P (args) = 1;
+    }
+  return args;
 }
 
 /* Expand an ASM statement with operands, handling output operands


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]