summaryrefslogtreecommitdiff
path: root/m68k-unknown-amigaos/recipes/patches/gcc/gcc.c-decl.c.p
blob: 6e7e353654e685947660ed977b12009b17441e73 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
--- gcc-3.4.6/gcc/c-decl.c	2013-05-19 20:09:27.000000000 +0200
+++ gcc/c-decl.c	2013-05-19 20:23:32.000000000 +0200
@@ -2960,7 +2960,7 @@
    and push that on the current scope.  */
 
 void
-push_parm_decl (tree parm)
+push_parm_decl (tree parm, tree asmspec)
 {
   tree decl;
   int old_dont_save_pending_sizes_p = 0;
@@ -2983,6 +2983,75 @@
 			 PARM, 0, NULL);
   decl_attributes (&decl, TREE_VALUE (parm), 0);
 
+  /* begin-GG-local: explicit register specification for parameters */
+  if (asmspec)
+#ifdef TARGET_AMIGAOS
+    {
+      const char *regname=TREE_STRING_POINTER(asmspec);
+      int regnum;
+      if ((regnum=decode_reg_name(regname))>=0)
+	{
+	  tree type=TREE_TYPE(decl);
+	  if (HARD_REGNO_MODE_OK(regnum, TYPE_MODE(type)))
+	    {
+	      tree t, attrs;
+	      /* Build tree for __attribute__ ((asm(regnum))). */
+#if 0
+	      /* This doesn't work well because of a bug in
+		 attribute_list_contained(), which passes list of arguments to
+		 simple_cst_equal() instead of passing every argument
+		 separately. */
+	      attrs=tree_cons(get_identifier("asm"), tree_cons(NULL_TREE,
+		    build_int_2_wide(regnum, 0), NULL_TREE), NULL_TREE);
+#else
+	      attrs=tree_cons(get_identifier("asm"),
+			      build_int_2_wide(regnum, 0), NULL_TREE);
+#endif
+#if 0
+	      /* build_type_attribute_variant() would seem to be more
+		 appropriate here. However, that function does not support
+		 attributes for parameters properly. It modifies
+		 TYPE_MAIN_VARIANT of a new type. As a result, comptypes()
+		 thinks that types of parameters in prototype and definition
+		 are different and issues error messages. See also comment
+		 below. */
+	      type=build_type_attribute_variant(type, attrs);
+#else
+	      /* First check whether such a type already exists - if yes, use
+		 that one. This is very important, since otherwise
+		 common_type() would think that it sees two different
+		 types and would try to merge them - this could result in
+		 warning messages. */
+	      for (t=TYPE_MAIN_VARIANT(type); t; t=TYPE_NEXT_VARIANT(t))
+		if (comptypes(t, type, COMPARE_STRICT)==1
+		    && attribute_list_equal(TYPE_ATTRIBUTES(t), attrs))
+		      break;
+	      if (t)
+		type=t;
+	      else
+		{
+		  /* Create a new variant, with differing attributes.
+		     (Hack! Type with differing attributes should no longer be
+		     a variant of its main type. See comment above for
+		     explanation why this was necessary). */
+		  type=build_type_copy(type);
+		  TYPE_ATTRIBUTES(type)=attrs;
+		}
+#endif
+	      TREE_TYPE(decl)=type;
+	    }
+	  else
+	    error ("%Jregister specified for '%D' isn't suitable for data type",
+		   decl, decl);
+	}
+      else
+	error ("invalid register name `%s'", regname);
+    }
+#else /* !TARGET_AMIGAOS */
+    error("explicit register specification for parameters is not supported for this target");
+#endif /* !TARGET_AMIGAOS */
+  /* end-GG-local */
+
   decl = pushdecl (decl);
 
   finish_decl (decl, NULL_TREE, NULL_TREE);