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]

Re: Named asm operands


[Fergus Henderson]
> On 07-May-2001, Espen Skoglund <esk@ira.uka.de> wrote:
>> The response I got on this list when I asked for having more
>> operands in asm constructs was that one really wants to have named
>> operands.  So, I went along and extended the asm constructs a bit.

> A test case or two would be nice.  Hmm, it's a bit tricky to add a
> portable test of asm.  I guess you could add some tests using
> `asm("" : ...)'...  hopefully all assemblers will accept the empty
> string!

Yes.  Problem is that such empty asms do not really tell you much in
this case since they do not make use of the named operands inside the
template.  Another solution would be to generate a comment using the
asm operands:

   asm ("/* val1: %[val1],  val2: %[val2] */"
        :[val1] "=r"(some_value)
        :[val2] "r"(another_value));

(Are C comments always legal inside assembler code?)

> What happens if I define two parameters with the same name?  Looking
> at your code, I think it will silently accept this, with any
> references to that name just being bound to the first of the two
> parameters with that name.  IMHO it ought to instead report an
> error.

Yes.  You're right.  Just after I submitted the patch earlier today I
realized that I forgot to add this test (I did manage to include it in
the documentation though :-), but didn't want to send in neither a
patch relative to the patch nor a completely new large patch.  Since
this was brough up now, however, I've attached an updated version of
the patched file in question (gcc/stmt.c).

	eSk



Index: stmt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/stmt.c,v
retrieving revision 1.195
diff -u -r1.195 stmt.c
--- stmt.c	2001/05/02 14:31:45	1.195
+++ stmt.c	2001/05/07 18:05:28
@@ -1314,7 +1314,7 @@
      const char *filename;
      int line;
 {
-  rtvec argvec, constraints;
+  rtvec argvec, constraints, opnames;
   rtx body;
   int ninputs = list_length (inputs);
   int noutputs = list_length (outputs);
@@ -1328,6 +1328,8 @@
   rtx *real_output_rtx = (rtx *) alloca (noutputs * sizeof (rtx));
   enum machine_mode *inout_mode
     = (enum machine_mode *) alloca (noutputs * sizeof (enum machine_mode));
+  const char **output_names
+    = (const char **) alloca (noutputs * sizeof (const char *));
   /* The insn we have emitted.  */
   rtx insn;
   int old_generating_concat_p = generating_concat_p;
@@ -1377,7 +1379,8 @@
   if (outputs || inputs)
     {
       tree tmp = TREE_PURPOSE (outputs ? outputs : inputs);
-      int nalternatives = n_occurrences (',', TREE_STRING_POINTER (tmp));
+      int nalternatives = n_occurrences
+	(',', TREE_STRING_POINTER (TREE_VALUE (tmp)));
       tree next = inputs;
 
       if (nalternatives + 1 > MAX_RECOG_ALTERNATIVES)
@@ -1389,7 +1392,8 @@
       tmp = outputs;
       while (tmp)
 	{
-	  const char *constraint = TREE_STRING_POINTER (TREE_PURPOSE (tmp));
+	  const char *constraint = TREE_STRING_POINTER
+	    (TREE_VALUE (TREE_PURPOSE (tmp)));
 
 	  if (n_occurrences (',', constraint) != nalternatives)
 	    {
@@ -1425,7 +1429,18 @@
 	 the worst that happens if we get it wrong is we issue an error
 	 message.  */
 
-      constraint = TREE_STRING_POINTER (TREE_PURPOSE (tail));
+      if (TREE_PURPOSE (TREE_PURPOSE (tail)) == NULL_TREE)
+	output_names[i] = empty_string;
+      else
+	{
+	  output_names[i] = IDENTIFIER_POINTER
+	    (TREE_PURPOSE (TREE_PURPOSE (tail)));
+	  for (j = 0; j < i; j++)
+	    if (strcmp (output_names[j], output_names[i]) == 0)
+	      error ("identical `asm' operand names: `%s'", output_names[i]);
+	}
+
+      constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (tail)));
       c_len = strlen (constraint);
 
       /* Allow the `=' or `+' to not be at the beginning of the string,
@@ -1596,21 +1611,25 @@
       return;
     }
 
-  /* Make vectors for the expression-rtx and constraint strings.  */
+  /* Make vectors for the expression-rtx, constraint strings and named
+     operands.  */
 
   argvec = rtvec_alloc (ninputs);
   constraints = rtvec_alloc (ninputs);
+  opnames = rtvec_alloc (ninputs);
 
   body = gen_rtx_ASM_OPERANDS ((noutputs == 0 ? VOIDmode
 				: GET_MODE (output_rtx[0])),
 			       TREE_STRING_POINTER (string), 
-			       empty_string, 0, argvec, constraints,
+			       empty_string, empty_string, 0,
+			       argvec, constraints, opnames,
 			       filename, line);
 
   MEM_VOLATILE_P (body) = vol;
 
   /* Eval the inputs and put them into ARGVEC.
-     Put their constraints into ASM_INPUTs and store in CONSTRAINTS.  */
+     Put their constraints into ASM_INPUTs and store in CONSTRAINTS.
+     Store operand names in OPNAMES.  */
 
   i = 0;
   for (tail = inputs; tail; tail = TREE_CHAIN (tail))
@@ -1618,6 +1637,7 @@
       int j;
       int allows_reg = 0, allows_mem = 0;
       const char *constraint, *orig_constraint;
+      const char *opname;
       int c_len;
       rtx op;
 
@@ -1635,7 +1655,20 @@
 	  return;
 	}
 
-      constraint = TREE_STRING_POINTER (TREE_PURPOSE (tail));
+      if (TREE_PURPOSE (TREE_PURPOSE (tail)) == NULL_TREE)
+	opname = empty_string;
+      else
+	{
+	  opname = IDENTIFIER_POINTER (TREE_PURPOSE (TREE_PURPOSE (tail)));
+	  for (j = 0; j < noutputs; j++)
+	    if (strcmp (output_names[j], opname) == 0)
+	      error ("identical `asm' operand names: `%s'", opname);
+	  for (j = 0; j < i; j++)
+	    if (strcmp (ASM_OPERANDS_INPUT_NAME (body, j), opname) == 0)
+	      error ("identical `asm' operand names: `%s'", opname);
+	}
+
+      constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (tail)));
       c_len = strlen (constraint);
       orig_constraint = constraint;
 
@@ -1697,7 +1730,8 @@
 		for (j = constraint[j] - '0'; j > 0; --j)
 		  o = TREE_CHAIN (o);
 
-		constraint = TREE_STRING_POINTER (TREE_PURPOSE (o));
+		constraint = TREE_STRING_POINTER
+		  (TREE_VALUE (TREE_PURPOSE (o)));
 		c_len = strlen (constraint);
 		j = 0;
 		break;
@@ -1787,6 +1821,10 @@
       ASM_OPERANDS_INPUT_CONSTRAINT_EXP (body, i)
 	= gen_rtx_ASM_INPUT (TYPE_MODE (TREE_TYPE (TREE_VALUE (tail))),
 			     orig_constraint);
+
+      ASM_OPERANDS_INPUT_NAME_EXP (body, i)
+	= gen_rtx_ASM_INPUT (TYPE_MODE (TREE_TYPE (TREE_VALUE (tail))),
+			     opname);
       i++;
     }
 
@@ -1811,19 +1849,22 @@
 	= output_rtx[j];
       ASM_OPERANDS_INPUT_CONSTRAINT_EXP (body, ninputs - ninout + i)
 	= gen_rtx_ASM_INPUT (inout_mode[i], digit_string (j));
+      ASM_OPERANDS_INPUT_NAME_EXP (body, ninputs - ninout + i)
+	= gen_rtx_ASM_INPUT (inout_mode[i], output_names[j]);
     }
 
   generating_concat_p = old_generating_concat_p;
 
   /* Now, for each output, construct an rtx
-     (set OUTPUT (asm_operands INSN OUTPUTNUMBER OUTPUTCONSTRAINT
-			       ARGVEC CONSTRAINTS))
+     (set OUTPUT (asm_operands INSN OUTPUTNUMBER OUTPUTCONSTRAINT OUTPUTNAME
+			       ARGVEC CONSTRAINTS OPNAMES))
      If there is more than one, put them inside a PARALLEL.  */
 
   if (noutputs == 1 && nclobbers == 0)
     {
       ASM_OPERANDS_OUTPUT_CONSTRAINT (body)
-	= TREE_STRING_POINTER (TREE_PURPOSE (outputs));
+	= TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (outputs)));
+      ASM_OPERANDS_OUTPUT_NAME (body) = output_names[0];
       insn = emit_insn (gen_rtx_SET (VOIDmode, output_rtx[0], body));
     }
 
@@ -1852,8 +1893,9 @@
 			   gen_rtx_ASM_OPERANDS
 			   (GET_MODE (output_rtx[i]),
 			    TREE_STRING_POINTER (string),
-			    TREE_STRING_POINTER (TREE_PURPOSE (tail)),
-			    i, argvec, constraints,
+			    TREE_STRING_POINTER
+			    (TREE_VALUE (TREE_PURPOSE (tail))),
+			    output_names[i], i, argvec, constraints, opnames,
 			    filename, line));
 
 	  MEM_VOLATILE_P (SET_SRC (XVECEXP (body, 0, i))) = vol;


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