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);
|