Hi, this patch has some impacts to the C front-end, and I'd like to know wether my approach is correct before finalizing it. So comments are welcome.
It implements the VMS 'pragma pointer_size 32/64/short/long', which change the default size of a pointer. This feature allows to use a 32 bits or a 64 bits ABI with only one C library (there are other weirdness to make this possible, but the main feature is this one). This feature was already supported by Ada (using pragma size), and by the __attribute__(mode (XX)), so the back-end stuff is already present. The patch is simple: the C front-end will now calls c_build_pointer_type (instead of build_pointer_type), which in turn calls build_pointer_type_for_mode using the right mode. The handling of the pragma pointer_size simply change the pointer mode for C. I haven't tried to change other C++ or Obj-C front-ends, because I haven't yet investigated how they deal with this option on VMS. This patch was tested on ia64 OpenVMS and also by bootstrapping gcc on x86-64 Darwin. Tristan. 2012-03-06 Tristan Gingold <ging...@adacore.com> * c-tree.h (c_default_pointer_mode): New variable. * c-decl.c (c_default_pointer_mode): New variable. (c_build_pointer_type): New function. (grokdeclarator): Call c_build_pointer_type instead of build_pointer_type. * config/vms/vms-c.c: Include c-tree.h (saved_pointer_mode): New variable. (handle_pragma_pointer_size): New function. (vms_pragma_pointer_size, vms_pragma_required_pointer_size): Likewise. (vms_c_register_pragma): Register __pointer_size and __required_pointer_size pragmas. diff --git a/gcc/c-decl.c b/gcc/c-decl.c index de46578..160d393 100644 --- a/gcc/c-decl.c +++ b/gcc/c-decl.c @@ -146,6 +146,10 @@ static int warn_about_return_type; static bool undef_nested_function; +/* Mode used to build pointers (VOIDmode means ptr_mode). */ + +enum machine_mode c_default_pointer_mode = VOIDmode; + /* Each c_binding structure describes one binding of an identifier to a decl. All the decls in a scope - irrespective of namespace - are @@ -558,6 +562,23 @@ add_stmt (tree t) return t; } +/* Build a pointer type using the default pointer mode. */ + +static tree +c_build_pointer_type (tree to_type) +{ + addr_space_t as = to_type == error_mark_node? ADDR_SPACE_GENERIC + : TYPE_ADDR_SPACE (to_type); + enum machine_mode pointer_mode; + + if (as != ADDR_SPACE_GENERIC || c_default_pointer_mode == VOIDmode) + pointer_mode = targetm.addr_space.pointer_mode (as); + else + pointer_mode = c_default_pointer_mode; + return build_pointer_type_for_mode (to_type, pointer_mode, false); +} + + /* Return true if we will want to say something if a goto statement crosses DECL. */ @@ -5683,7 +5704,7 @@ grokdeclarator (const struct c_declarator *declarator, TYPE_NAME (type) = decl; } - type = build_pointer_type (type); + type = c_build_pointer_type (type); /* Process type qualifiers (such as const or volatile) that were given inside the `*'. */ @@ -5918,7 +5939,7 @@ grokdeclarator (const struct c_declarator *declarator, type = TREE_TYPE (type); if (type_quals) type = c_build_qualified_type (type, type_quals); - type = build_pointer_type (type); + type = c_build_pointer_type (type); type_quals = array_ptr_quals; if (type_quals) type = c_build_qualified_type (type, type_quals); @@ -5937,7 +5958,7 @@ grokdeclarator (const struct c_declarator *declarator, "ISO C forbids qualified function types"); if (type_quals) type = c_build_qualified_type (type, type_quals); - type = build_pointer_type (type); + type = c_build_pointer_type (type); type_quals = TYPE_UNQUALIFIED; } else if (type_quals) diff --git a/gcc/c-tree.h b/gcc/c-tree.h index 51c660c..db60935 100644 --- a/gcc/c-tree.h +++ b/gcc/c-tree.h @@ -625,6 +625,10 @@ extern int current_function_returns_abnormally; extern int system_header_p; +/* Mode used to build pointers (VOIDmode means ptr_mode). */ + +extern enum machine_mode c_default_pointer_mode; + /* In c-decl.c */ extern void c_finish_incomplete_decl (tree); extern void c_write_global_declarations (void); diff --git a/gcc/config/vms/vms-c.c b/gcc/config/vms/vms-c.c index 4a2d19c..e4f8493 100644 --- a/gcc/config/vms/vms-c.c +++ b/gcc/config/vms/vms-c.c @@ -27,6 +27,7 @@ along with GCC; see the file COPYING3. If not see #include "tree.h" #include "c-family/c-pragma.h" #include "c-family/c-common.h" +#include "c-tree.h" #include "toplev.h" #include "ggc.h" #include "tm_p.h" @@ -283,6 +284,70 @@ vms_pragma_extern_prefix (cpp_reader * ARG_UNUSED (dummy)) } } +/* #pragma __pointer_size */ + +static enum machine_mode saved_pointer_mode; + +static void +handle_pragma_pointer_size (const char *pragma_name) +{ + enum cpp_ttype tok; + tree x; + + tok = pragma_lex (&x); + if (tok == CPP_NAME) + { + const char *op = IDENTIFIER_POINTER (x); + + if (!strcmp (op, "__save")) + saved_pointer_mode = c_default_pointer_mode; + else if (!strcmp (op, "__restore")) + c_default_pointer_mode = saved_pointer_mode; + else if (!strcmp (op, "__short")) + c_default_pointer_mode = SImode; + else if (!strcmp (op, "__long")) + c_default_pointer_mode = DImode; + else + error ("malformed %<#pragma %s%>, ignoring", pragma_name); + } + else if (tok == CPP_NUMBER) + { + int val; + + if (TREE_CODE (x) == INTEGER_CST) + val = TREE_INT_CST_LOW (x); + else + val = -1; + + if (val == 32) + c_default_pointer_mode = SImode; + else if (val == 64) + c_default_pointer_mode = DImode; + else + error ("invalid constant in %<#pragma %s%>", pragma_name); + } + else + { + error ("malformed %<#pragma %s%>, ignoring", pragma_name); + } +} + +static void +vms_pragma_pointer_size (cpp_reader * ARG_UNUSED (dummy)) +{ + /* Ignore if no -mpointer-size option. */ + if (flag_vms_pointer_size == VMS_POINTER_SIZE_NONE) + return; + + handle_pragma_pointer_size ("pointer_size"); +} + +static void +vms_pragma_required_pointer_size (cpp_reader * ARG_UNUSED (dummy)) +{ + handle_pragma_pointer_size ("required_pointer_size"); +} + /* Add vms-specific pragma. */ void @@ -298,6 +363,10 @@ vms_c_register_pragma (void) vms_pragma_nomember_alignment); c_register_pragma_with_expansion (NULL, "nomember_alignment", vms_pragma_nomember_alignment); + c_register_pragma (NULL, "__pointer_size", + vms_pragma_pointer_size); + c_register_pragma (NULL, "__required_pointer_size", + vms_pragma_required_pointer_size); c_register_pragma (NULL, "__extern_model", vms_pragma_extern_model); c_register_pragma (NULL, "extern_model", vms_pragma_extern_model); c_register_pragma (NULL, "__message", vms_pragma_message);