diff options
Diffstat (limited to 'ppc-amigaos/recipes/patches/gcc/0002-Added-new-function-attribute-lineartags-and-pragma-a.p')
-rw-r--r-- | ppc-amigaos/recipes/patches/gcc/0002-Added-new-function-attribute-lineartags-and-pragma-a.p | 376 |
1 files changed, 376 insertions, 0 deletions
diff --git a/ppc-amigaos/recipes/patches/gcc/0002-Added-new-function-attribute-lineartags-and-pragma-a.p b/ppc-amigaos/recipes/patches/gcc/0002-Added-new-function-attribute-lineartags-and-pragma-a.p new file mode 100644 index 0000000..69a33a6 --- /dev/null +++ b/ppc-amigaos/recipes/patches/gcc/0002-Added-new-function-attribute-lineartags-and-pragma-a.p @@ -0,0 +1,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 + |