summaryrefslogtreecommitdiff
path: root/ppc-amigaos/recipes/patches/gcc/0002-Added-new-function-attribute-lineartags-and-pragma-a.p
blob: 69a33a6c256dcd3bf775e780413f48fefb0570ed (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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
From c8d51b6ed56c643f9744d7a18fee3b13a76b98d3 Mon Sep 17 00:00:00 2001
From: Sebastian Bauer <mail@sebastianbauer.info>
Date: Fri, 14 Nov 2014 20:03:56 +0100
Subject: [PATCH 2/6] Added new function attribute "lineartags" and pragma
 "amigaos tagtype".

Functions that have the lineartags attribute are assumed to be functions
with tags, in which case type checking is now enabled. That is, the value
that follow a specific tag is assumed to be a certain type. If this is
not the case, the compiler will warn.

The compiler can be taught about that types via the new pragma
#pragma amigaos tagtype(TYPE)
which is written before an "enum" or a "static const int" that defines
the number of the tag.

For instance:

#pragma amigaos tagtype(struct Screen *)
static const int WA_CustomScreen = WA_Dummy + 0x0D;

 or

#pragma amigaos tagtype(struct Screen *)
enum {WA_CustomScreen = WA_Dummy + 0x0D};

is possible now.

It is not very robust yet wrt to catching misuses of the new feature.
For instance, no check is done that the attribute is applied to varargs
functions.
---
 gcc/c-family/c-pragma.c            |  10 +++
 gcc/c/c-parser.c                   | 129 +++++++++++++++++++++++++++++++++++++
 gcc/c/c-typeck.c                   |  24 +++++++
 gcc/config/rs6000/amigaos-protos.h |   1 +
 gcc/config/rs6000/amigaos.c        |   7 ++
 5 files changed, 171 insertions(+)

diff --git a/gcc/c-family/c-pragma.c b/gcc/c-family/c-pragma.c
index 6894f0e7c3d1ea932ff05f370680be3d18dfcf94..24278250901bfa75c9aae9be63a62351f33e390e 100644
--- a/gcc/c-family/c-pragma.c
+++ b/gcc/c-family/c-pragma.c
@@ -1066,12 +1066,21 @@ handle_pragma_message (cpp_reader *ARG_UNUSED(dummy))
     warning (OPT_Wpragmas, "junk at end of %<#pragma message%>");
 
   if (TREE_STRING_LENGTH (message) > 1)
     inform (input_location, "#pragma message: %s", TREE_STRING_POINTER (message));
 }
 
+/* This is queried by the invoker of the handler */
+int was_tagtypepragma;
+/* Tagtype pragma */
+static void
+handle_pragma_tagtype (cpp_reader *reader)
+{
+  was_tagtypepragma = 1;
+}
+
 /* Mark whether the current location is valid for a STDC pragma.  */
 
 static bool valid_location_for_stdc_pragma;
 
 void
 mark_valid_location_for_stdc_pragma (bool flag)
@@ -1483,12 +1492,13 @@ init_pragma (void)
 
   c_register_pragma_with_expansion (0, "redefine_extname",
 				    handle_pragma_redefine_extname);
 
   c_register_pragma_with_expansion (0, "message", handle_pragma_message);
 
+  c_register_pragma_with_expansion ("amigaos", "tagtype", handle_pragma_tagtype);
 #ifdef REGISTER_TARGET_PRAGMAS
   REGISTER_TARGET_PRAGMAS ();
 #endif
 
   /* Allow plugins to register their own pragmas. */
   invoke_plugin_callbacks (PLUGIN_PRAGMAS, NULL);
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 86cbc404a4c10edac0ce2341ae0099f624ee36ea..cc77530b090576db35610468052d84763c3965fd 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -80,12 +80,74 @@ along with GCC; see the file COPYING3.  If not see
 #include "cgraph.h"
 #include "plugin.h"
 #include "omp-low.h"
 #include "builtins.h"
 #include "gomp-constants.h"
 
+static htab_t amigaos_tagdecl_to_type;
+
+struct amigaos_hash_type
+{
+  tree decl;
+  tree type;
+};
+
+static hashval_t
+amigaos_hash_descriptor (const void *p)
+{
+  return htab_hash_pointer (((const amigaos_hash_type *)p)->decl);
+}
+
+static int
+amigaos_eq_descriptor (const void *p1, const void *p2)
+{
+  return ((const amigaos_hash_type *)p1)->decl == ((const amigaos_hash_type *)p2)->decl;
+}
+
+/**
+ * Returns the tag type that is associated with the given type.
+ *
+ * @param type
+ * @return
+ */
+tree amigaos_get_type_associated_tagtype(tree decl)
+{
+  amigaos_hash_type aht = {decl, 0};
+  amigaos_hash_type *faht;
+
+  if (!amigaos_tagdecl_to_type)
+    return NULL;
+
+  faht = (amigaos_hash_type *)htab_find(amigaos_tagdecl_to_type, &aht);
+  if (!faht)
+    return NULL;
+  return faht->type;
+}
+
+static void amigaos_put_type_associated_tagtype(tree decl, tree type)
+{
+  gcc_assert(decl);
+
+  if (!amigaos_tagdecl_to_type)
+    amigaos_tagdecl_to_type = htab_create (10, amigaos_hash_descriptor, amigaos_eq_descriptor, NULL);
+
+  amigaos_hash_type *aht = (amigaos_hash_type *)xmalloc(sizeof(*aht));
+  aht->decl = decl;
+  aht->type = type;
+
+  void **pentry = htab_find_slot (amigaos_tagdecl_to_type, aht, INSERT);
+  gcc_assert(pentry);
+  gcc_assert(*pentry == NULL);
+  *pentry = aht;
+}
+
+/**
+ * Contains the tagtype that is currently processed or NULL_TREE
+ * if no tagtype is processed.
+ */
+static tree amigaos_current_tagtype;
 
 /* Initialization routine for this file.  */
 
 void
 c_parse_init (void)
 {
@@ -2390,12 +2452,15 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
 	    goto out;
 	  attrs_ok = true;
 	  seen_type = true;
 	  t = c_parser_enum_specifier (parser);
           invoke_plugin_callbacks (PLUGIN_FINISH_TYPE, t.spec);
 	  declspecs_add_type (loc, specs, t);
+	  /* Handle special tagtype enhanced enums */
+	  if (amigaos_current_tagtype != NULL_TREE && t.spec != NULL_TREE)
+	    amigaos_put_type_associated_tagtype(t.spec, amigaos_current_tagtype);
 	  break;
 	case RID_STRUCT:
 	case RID_UNION:
 	  if (!typespec_ok)
 	    goto out;
 	  attrs_ok = true;
@@ -9590,12 +9655,32 @@ c_parser_objc_at_dynamic_declaration (c_parser *parser)
     }
   c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
   objc_add_dynamic_declaration (loc, list);
 }
 
 
+/**
+ * This function is called whenever a declaration was finished that was preceded
+ * by a tagtype pragma.
+ *
+ * @param gcc_data will be the finished declaration
+ * @param user_data will be the parsed c type of the declaration (c_type_name *)
+ *  that was specified ahead of the declaration via the pragma.
+ */
+static void amigaos_tagtype_finish_decl_callback (void *gcc_data, void *user_data)
+{
+  tree decl = (tree)gcc_data;
+  c_type_name *ctype = (c_type_name*)user_data;
+  tree type = groktypename (ctype, NULL, NULL);
+
+  /* TODO: All sorts of checks */
+
+  /* Now put the association in our own hash table */
+  amigaos_put_type_associated_tagtype(decl, type);
+}
+
 /* Handle pragmas.  Some OpenMP pragmas are associated with, and therefore
    should be considered, statements.  ALLOW_STMT is true if we're within
    the context of a function and such pragmas are to be allowed.  Returns
    true if we actually parsed such a pragma.  */
 
 static bool
@@ -9777,12 +9862,56 @@ c_parser_pragma (c_parser *parser, enum pragma_context context)
       break;
     }
 
   c_parser_consume_pragma (parser);
   c_invoke_pragma_handler (id);
 
+  /* If was_tagtypepragma is set, the pragma was a tagtype one,
+   * which, at the moment, cannot easily handled outside of this
+   * file.
+   */
+  extern int was_tagtypepragma;
+  if (was_tagtypepragma)
+  {
+    c_token *tok = c_parser_peek_token (the_parser);
+    enum cpp_ttype ret = tok->type;
+    c_parser_consume_token(parser);
+
+    c_type_name *ctype = c_parser_type_name(parser);
+    tree ctypetree = groktypename (ctype, NULL, NULL);
+
+    /* Make the parsed type available to all functions called from here on */
+    amigaos_current_tagtype = ctypetree;
+
+    tok = c_parser_peek_token (the_parser);
+    ret = tok->type;
+    c_parser_consume_token(parser);
+    c_parser_skip_to_pragma_eol(parser);
+
+    tok = c_parser_peek_token (the_parser);
+    ret = tok->type;
+
+    /* Parse the line that follows. We will register for a PLUGIN_FINISH_DECL event
+     * to minimize contermination
+     */
+    bool old_flag_plugin_added = flag_plugin_added;
+    register_callback ("amigaos-tagtype", PLUGIN_FINISH_DECL,
+                       amigaos_tagtype_finish_decl_callback,
+                       ctype);
+    flag_plugin_added = 1;
+    c_parser_declaration_or_fndef(parser, false, false, true, false, true, NULL, vNULL);
+    unregister_callback ("amigaos-tagtype", PLUGIN_FINISH_DECL);
+    flag_plugin_added = old_flag_plugin_added;
+    /* Reset the variable that is set in the pragma handler */
+    was_tagtypepragma = 0;
+    /* The tagtype has been processed */
+    amigaos_current_tagtype = NULL_TREE;
+    return false;
+  }
+
+
   /* Skip to EOL, but suppress any error message.  Those will have been
      generated by the handler routine through calling error, as opposed
      to calling c_parser_error.  */
   parser->error = true;
   c_parser_skip_to_pragma_eol (parser);
 
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index a98622b16f546b88eb7fdce9ca7631c3ca37470a..2c03a10f1127c2bec5d9280ecc2f786fd5d13153 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -3100,12 +3100,14 @@ convert_arguments (location_t loc, vec<location_t> arg_loc, tree typelist,
   unsigned int parmnum;
   bool error_args = false;
   const bool type_generic = fundecl
     && lookup_attribute ("type generic", TYPE_ATTRIBUTES (TREE_TYPE (fundecl)));
   bool type_generic_remove_excess_precision = false;
   tree selector;
+  const bool lineartags = fundecl
+    && lookup_attribute ("lineartags", TYPE_ATTRIBUTES (TREE_TYPE (fundecl)));
 
   /* Change pointer to function to the function itself for
      diagnostics.  */
   if (TREE_CODE (function) == ADDR_EXPR
       && TREE_CODE (TREE_OPERAND (function, 0)) == FUNCTION_DECL)
     function = TREE_OPERAND (function, 0);
@@ -3139,12 +3141,14 @@ convert_arguments (location_t loc, vec<location_t> arg_loc, tree typelist,
   if (flag_cilkplus && fundecl && is_cilkplus_reduce_builtin (fundecl))
     return vec_safe_length (values);
 
   /* Scan the given expressions and types, producing individual
      converted arguments.  */
 
+  tree prev_tagtype = NULL_TREE;
+
   for (typetail = typelist, parmnum = 0;
        values && values->iterate (parmnum, &val);
        ++parmnum)
     {
       tree type = typetail ? TREE_VALUE (typetail) : 0;
       tree valtype = TREE_TYPE (val);
@@ -3193,12 +3197,32 @@ convert_arguments (location_t loc, vec<location_t> arg_loc, tree typelist,
 	}
       val = c_fully_fold (val, false, NULL);
       STRIP_TYPE_NOPS (val);
 
       val = require_complete_type (val);
 
+      /* If this is a function call with linear tags try to improve the expected
+       * type on base of recorded tag <-> type mapping.
+       */
+      if (lineartags && type == 0)
+        {
+          extern tree amigaos_get_type_associated_tagtype(tree type);
+
+          if (prev_tagtype)
+            {
+              type = prev_tagtype;
+              prev_tagtype = NULL_TREE;
+            }
+          else
+            {
+              prev_tagtype = amigaos_get_type_associated_tagtype(val);
+              if (!prev_tagtype)
+                prev_tagtype = amigaos_get_type_associated_tagtype((*origtypes)[parmnum]);
+            }
+        }
+
       if (type != 0)
 	{
 	  /* Formal parm type is specified by a function prototype.  */
 
 	  if (type == error_mark_node || !COMPLETE_TYPE_P (type))
 	    {
diff --git a/gcc/config/rs6000/amigaos-protos.h b/gcc/config/rs6000/amigaos-protos.h
index eb5f8fc5f3d546b8d8e1cdd8118a3085079df50e..3b8c994cdbd192eaf7112c780f0106a4d96cbb90 100644
--- a/gcc/config/rs6000/amigaos-protos.h
+++ b/gcc/config/rs6000/amigaos-protos.h
@@ -27,12 +27,13 @@ extern void amigaos_function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode,
 extern struct rtx_def *amigaos_function_arg (CUMULATIVE_ARGS *, enum machine_mode, tree, int);
 extern void amigaos_expand_builtin_va_start (tree valist, rtx nextarg);
 extern struct rtx_def *amigaos_expand_builtin_saveregs (void);
 extern void amigaos_init_builtins (void);
 extern rtx amigaos_expand_builtin (tree, rtx, rtx, enum machine_mode, int, bool*);
 extern tree amigaos_handle_linearvarargs_attribute (tree *, tree, tree, int, bool*);
+extern tree amigaos_handle_lineartags_attribute (tree *, tree, tree, int, bool*);
 extern tree amigaos_handle_baserel_restore_attribute (tree *, tree, tree, int, bool*);
 extern tree amigaos_handle_force_no_baserel_attribute (tree *, tree, tree, int, bool*);
 extern tree amigaos_handle_check68kfuncptr_attribute (tree *, tree, tree, int, bool*);
 extern rtx amigaos_legitimize_baserel_address (rtx addr);
 extern int amigaos_baserel_operand(rtx x);
 extern int amigaos_not_baserel_tree_p(tree decl);
diff --git a/gcc/config/rs6000/amigaos.c b/gcc/config/rs6000/amigaos.c
index 0f575a38e4dc4aac0b454c56bf62f625c0f7eb9c..ccf4f912cb66cd424a2398c6535e05fa493f39f1 100644
--- a/gcc/config/rs6000/amigaos.c
+++ b/gcc/config/rs6000/amigaos.c
@@ -345,12 +345,19 @@ amigaos_handle_linearvarargs_attribute (tree *node, tree name,
       *no_add_attrs = true;
     }
 
   return NULL_TREE;
 }
 
+tree
+amigaos_handle_lineartags_attribute (tree *node, tree name, tree args, int flags, bool *no_add_attrs)
+{
+  /* TODO: This function should applied only to functions or methods */
+  return NULL_TREE;
+}
+
 
 /* Generate code for base relative access */
 
 rtx
 amigaos_legitimize_baserel_address (rtx addr)
 {
-- 
2.1.4