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

Reply via email to