diff mbox

[RFC] : Add support for pragma pointer_size

Message ID E09269D8-43D5-4D3B-88E2-AE4EC75FDA1A@adacore.com
State New
Headers show

Commit Message

Tristan Gingold March 6, 2012, 1:09 p.m. UTC
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  <gingold@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.

Comments

Joseph Myers March 6, 2012, 5:34 p.m. UTC | #1
On Tue, 6 Mar 2012, Tristan Gingold wrote:

> 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.

There seem to be quite a lot of build_pointer_type calls in the C front 
end (and in c-common.c) that you haven't changed.  Could you explain the 
rule for when a call should or should not be changed, and how it applies 
to all these calls?
Tristan Gingold March 7, 2012, 8:54 a.m. UTC | #2
On Mar 6, 2012, at 6:34 PM, Joseph S. Myers wrote:

> On Tue, 6 Mar 2012, Tristan Gingold wrote:
> 
>> 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.
> 
> There seem to be quite a lot of build_pointer_type calls in the C front 
> end (and in c-common.c) that you haven't changed.  Could you explain the 
> rule for when a call should or should not be changed, and how it applies 
> to all these calls?

The global approach is to have the same effect as a default __attribute__((mode(SI/DImode))) on pointers declared by users so that layouts match.  That's why only grokdeclarator is changed.

There might be bugs with this approach (e.g. it looks like c-common.c:handle_noreturn_attribute doesn't preserve the mode of the pointer to function), but my understanding is that they also correspond to bugs of __attribute__((mode ())) applied to pointer.  The later one isn't well tested and one advantage of the VMS port is that it will test it much more (as there are many pragma pointer_size in VMS headers).

I haven't tried to exactly follow the DEC-C rules, because:
- they aren't formally written
- the current behavior of the front and middle end is already correct

I agree that it is possible to concoct tests (e.g. using sizeof) that will return different results between gcc and DEC-C, but my purpose is to be reasonable compatible, not fully compatible.  There are some features (such as supporting VAX float) that I don't plan to implement :-)

Tristan.
Joseph Myers March 7, 2012, 6:42 p.m. UTC | #3
On Wed, 7 Mar 2012, Tristan Gingold wrote:

> On Mar 6, 2012, at 6:34 PM, Joseph S. Myers wrote:
> 
> > On Tue, 6 Mar 2012, Tristan Gingold wrote:
> > 
> >> 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.
> > 
> > There seem to be quite a lot of build_pointer_type calls in the C front 
> > end (and in c-common.c) that you haven't changed.  Could you explain the 
> > rule for when a call should or should not be changed, and how it applies 
> > to all these calls?
> 
> The global approach is to have the same effect as a default 
> __attribute__((mode(SI/DImode))) on pointers declared by users so that 
> layouts match.  That's why only grokdeclarator is changed.
> 
> There might be bugs with this approach (e.g. it looks like 
> c-common.c:handle_noreturn_attribute doesn't preserve the mode of the 
> pointer to function), but my understanding is that they also correspond 
> to bugs of __attribute__((mode ())) applied to pointer.  The later one 
> isn't well tested and one advantage of the VMS port is that it will test 
> it much more (as there are many pragma pointer_size in VMS headers).

So those places would need to change to use build_pointer_type_for_mode as 
is done for composite types in c-typeck.c:composite_type, for example?

I think the patch at least needs a (VMS-specific?) testcase that tests the 
new pragma (presuming the testsuite can be run for VMS targets) even if 
some cases can't be tested until they are fixed.
Tristan Gingold March 8, 2012, 1:49 p.m. UTC | #4
On Mar 7, 2012, at 7:42 PM, Joseph S. Myers wrote:

> On Wed, 7 Mar 2012, Tristan Gingold wrote:
> 
>> On Mar 6, 2012, at 6:34 PM, Joseph S. Myers wrote:
>> 
>>> On Tue, 6 Mar 2012, Tristan Gingold wrote:
>>> 
>>>> 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.
>>> 
>>> There seem to be quite a lot of build_pointer_type calls in the C front 
>>> end (and in c-common.c) that you haven't changed.  Could you explain the 
>>> rule for when a call should or should not be changed, and how it applies 
>>> to all these calls?
>> 
>> The global approach is to have the same effect as a default 
>> __attribute__((mode(SI/DImode))) on pointers declared by users so that 
>> layouts match.  That's why only grokdeclarator is changed.
>> 
>> There might be bugs with this approach (e.g. it looks like 
>> c-common.c:handle_noreturn_attribute doesn't preserve the mode of the 
>> pointer to function), but my understanding is that they also correspond 
>> to bugs of __attribute__((mode ())) applied to pointer.  The later one 
>> isn't well tested and one advantage of the VMS port is that it will test 
>> it much more (as there are many pragma pointer_size in VMS headers).
> 
> So those places would need to change to use build_pointer_type_for_mode as 
> is done for composite types in c-typeck.c:composite_type, for example?

Yes.

> I think the patch at least needs a (VMS-specific?) testcase that tests the 
> new pragma (presuming the testsuite can be run for VMS targets) even if 
> some cases can't be tested until they are fixed.

Argh, that's an issue.  We don't run the gcc test suite natively on VMS
because there is no port of Dejagnu (if ever doable) to VMS.  We haven't tried
to test a cross-compiler (and running the executable on the VMS host) because
an early attempt for another test suite pointed out slowness and reliability
issues.  VMS machines could be considered as slow from today's standard POV.
I haven't found a method to run only the compile tests and skip the executing one.
Is it possible to do that with the gcc test suite ?  That's would be very
useful to test cross compilers.

But I am not worried about the tests of '#pragma pointer_size' per see, as there
are very present in system headers and thus simply building a cross-compiler
(and much more certainly if Ada is enabled) would thoroughly test it.  So I think
this patch is test by building the compiler (not now but as soon as I add the
builtin macros that protect this pragma in VMS headers).

For testing front-end handling of mixed sized pointers, I think we can fallback
to the mode __attribute__ and enabling these tests on platforms that support it
(mips64/linux, s390x).

Is this approach ok to you ?

Tristan.
Joseph Myers March 8, 2012, 3:18 p.m. UTC | #5
On Thu, 8 Mar 2012, Tristan Gingold wrote:

> Argh, that's an issue.  We don't run the gcc test suite natively on VMS
> because there is no port of Dejagnu (if ever doable) to VMS.  We haven't tried
> to test a cross-compiler (and running the executable on the VMS host) because
> an early attempt for another test suite pointed out slowness and reliability
> issues.  VMS machines could be considered as slow from today's standard POV.
> I haven't found a method to run only the compile tests and skip the executing one.
> Is it possible to do that with the gcc test suite ?  That's would be very
> useful to test cross compilers.

Thanks for the explanation.  I advise solving the unreliability issues for 
cross-testing to VMS (and living with the slowness), so that you can run 
the testsuite, but the patch is OK as-is.
Richard Henderson March 8, 2012, 6:08 p.m. UTC | #6
On 03/08/12 05:49, Tristan Gingold wrote:
> I haven't found a method to run only the compile tests and skip the executing one.
> Is it possible to do that with the gcc test suite ?  That's would be very
> useful to test cross compilers.

Set the "simulator" to be /bin/true.


r~
Mike Stump March 8, 2012, 6:10 p.m. UTC | #7
On Mar 8, 2012, at 5:49 AM, Tristan Gingold wrote:
> Argh, that's an issue.  We don't run the gcc test suite natively on VMS
> because there is no port of Dejagnu (if ever doable) to VMS.  We haven't tried
> to test a cross-compiler (and running the executable on the VMS host) because
> an early attempt for another test suite pointed out slowness and reliability
> issues.

dejagnu slices through this type of testing just fine.  dejagnu is also adept at handling reliability issues, its history is littered with unreliability and it is usually fairly easy to work around any unreliability.  Selecting targets that happen to be in a `working' state, powercycling them, as needed, noticing when things go wrong, retrying things a few times, as sometimes, something doesn't just work and so on.  Also, the cross testing can come in many flavors, you can use a simulator (if you have one) and do cross and test on simulator.  You can do this, without the simulator and just fail all the execute tests, you can do canadian cross controlling host to native host testing.  As for speed, well, it is all about latency and reliability, the lower the latency and the higher the reliability, the faster the testing, but, it is, what it is.  The modern testsuite might be 8 hour range or more, but overnight testing is better than no testing.  If you hide it behind a git send hook and stage everything through git and then push out from git as the testsuite passes...  you should be able to achieve a nice work-flow.

>  VMS machines could be considered as slow from today's standard POV.
> I haven't found a method to run only the compile tests and skip the executing one.
> Is it possible to do that with the gcc test suite ?

If you configure a cross compiler and do a make check, you'll just get a fast fail on all the execute tests.  If you just look for regressions, you'll notice this works just fine.  Sit back, don't worry about the execution failures.  When you wire up sim, just say the simulator is /bin/false or /bin/true (set_board_info sim /bin/false)

Feel free to email me directly if you need additional pointers.  It is fairly easy to setup, though, daunting, one has never done it before.
Tristan Gingold March 9, 2012, 9:47 a.m. UTC | #8
On Mar 8, 2012, at 7:10 PM, Mike Stump wrote:

> On Mar 8, 2012, at 5:49 AM, Tristan Gingold wrote:
>> Argh, that's an issue.  We don't run the gcc test suite natively on VMS
>> because there is no port of Dejagnu (if ever doable) to VMS.  We haven't tried
>> to test a cross-compiler (and running the executable on the VMS host) because
>> an early attempt for another test suite pointed out slowness and reliability
>> issues.
> 
> dejagnu slices through this type of testing just fine.  dejagnu is also adept at handling reliability issues, its history is littered with unreliability and it is usually fairly easy to work around any unreliability.  Selecting targets that happen to be in a `working' state, powercycling them, as needed, noticing when things go wrong, retrying things a few times, as sometimes, something doesn't just work and so on.  Also, the cross testing can come in many flavors, you can use a simulator (if you have one) and do cross and test on simulator.  You can do this, without the simulator and just fail all the execute tests, you can do canadian cross controlling host to native host testing.  As for speed, well, it is all about latency and reliability, the lower the latency and the higher the reliability, the faster the testing, but, it is, what it is.  The modern testsuite might be 8 hour range or more, but overnight testing is better than no testing.  If you hide it behind a git send hook and stage everything through git and then push out from git as the testsuite passes...  you should be able to achieve a nice work-flow.
> 
>> VMS machines could be considered as slow from today's standard POV.
>> I haven't found a method to run only the compile tests and skip the executing one.
>> Is it possible to do that with the gcc test suite ?
> 
> If you configure a cross compiler and do a make check, you'll just get a fast fail on all the execute tests.  If you just look for regressions, you'll notice this works just fine.  Sit back, don't worry about the execution failures.  When you wire up sim, just say the simulator is /bin/false or /bin/true (set_board_info sim /bin/false)
> 
> Feel free to email me directly if you need additional pointers.  It is fairly easy to setup, though, daunting, one has never done it before.

Thank you Mike for details.

I think I will investigate the cross compiler path first.

Tristan.
Tristan Gingold March 9, 2012, 12:47 p.m. UTC | #9
On Mar 8, 2012, at 4:18 PM, Joseph S. Myers wrote:

> On Thu, 8 Mar 2012, Tristan Gingold wrote:
> 
>> Argh, that's an issue.  We don't run the gcc test suite natively on VMS
>> because there is no port of Dejagnu (if ever doable) to VMS.  We haven't tried
>> to test a cross-compiler (and running the executable on the VMS host) because
>> an early attempt for another test suite pointed out slowness and reliability
>> issues.  VMS machines could be considered as slow from today's standard POV.
>> I haven't found a method to run only the compile tests and skip the executing one.
>> Is it possible to do that with the gcc test suite ?  That's would be very
>> useful to test cross compilers.
> 
> Thanks for the explanation.  I advise solving the unreliability issues for 
> cross-testing to VMS (and living with the slowness), so that you can run 
> the testsuite, but the patch is OK as-is.

Thank you for your comments.
No C regressions on x86_64-darwin after full bootstrap.
Now committed.

Tristan.
Gary Funck March 13, 2012, 8:57 p.m. UTC | #10
On 03/06/12 14:09:23, Tristan Gingold wrote:
> 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.
[...]

Joining this discussion a bit late ... I have a few questions.
This change impacts the GUPC branch, mainly because UPC introduces
pointers that are generally larger than conventional "C" pointers,
and thus some changes were needed in the "build pointer" area,
and that logic needed to be adjusted to work with this patch.

Here is the new c_build_pointer_type.  It a static function
constrained to be called from within the c-decl.c file wehre
it resides.

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

Here is the old build_pointer_type() in tree.c.  It is external/public
and is called from various places.

tree
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 = targetm.addr_space.pointer_mode (as);
  return build_pointer_type_for_mode (to_type, pointer_mode, false);
}

c_build_pointer_type () introduces c_default_pointer_mode
and uses it as long as:
   as == ADDR_SPACE_GENERIC && c_default_pointer_mode != VOIDmode
but build_pointer_type will not use c_default_pointer_mode.

My first question is: are there still contexts where build_pointer_type()
is called to compile "C" statements/expressions for cases not
covered by the calls within c-decl.c?  I ask, because we tried
moving our checks for UPC pointer-to-shared types from
build_pointer_type() into only c_build_pointer_type() and
ran into calls to build_pointer_type() that still passed
in UPC pointer-to-shared typed objects.  What this may
indicate is that there are situations where the new
c_default_pointer_mode may need to be applied when
build_pointer_type() is called.  I don't recall off-hand
when these situations came up, but it might be easy enough
to put some assertions in build_pointer_type() and then
run the "C" test suite and see what turns up.

Thus, I wonder if it might not be best to generalize
build_pointer_type() instead of introducing c_build_pointer_type()
and dealing with any "C" specific checks (somehow) there?

Thanks,
- Gary
Tristan Gingold March 14, 2012, 8:13 a.m. UTC | #11
On Mar 13, 2012, at 9:57 PM, Gary Funck wrote:

> On 03/06/12 14:09:23, Tristan Gingold wrote:
>> 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.
> [...]
> 
> Joining this discussion a bit late ... I have a few questions.
> This change impacts the GUPC branch, mainly because UPC introduces
> pointers that are generally larger than conventional "C" pointers,
> and thus some changes were needed in the "build pointer" area,
> and that logic needed to be adjusted to work with this patch.
> 
> Here is the new c_build_pointer_type.  It a static function
> constrained to be called from within the c-decl.c file wehre
> it resides.
> 
> 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);
> }
> 
> Here is the old build_pointer_type() in tree.c.  It is external/public
> and is called from various places.
> 
> tree
> 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 = targetm.addr_space.pointer_mode (as);
>  return build_pointer_type_for_mode (to_type, pointer_mode, false);
> }
> 
> c_build_pointer_type () introduces c_default_pointer_mode
> and uses it as long as:
>   as == ADDR_SPACE_GENERIC && c_default_pointer_mode != VOIDmode
> but build_pointer_type will not use c_default_pointer_mode.
> 
> My first question is: are there still contexts where build_pointer_type()
> is called to compile "C" statements/expressions for cases not
> covered by the calls within c-decl.c?

Yes.  In the discussion, Joseph Myers has pointed them.
Some of them are bugs (but should be replaced by build_pointer_type_for_mode),
others aren't incorrect (e.g. for built-in functions).

Currently c_build_pointer_type is called for user declared pointer types.

>  I ask, because we tried
> moving our checks for UPC pointer-to-shared types from
> build_pointer_type() into only c_build_pointer_type() and
> ran into calls to build_pointer_type() that still passed
> in UPC pointer-to-shared typed objects.  What this may
> indicate is that there are situations where the new
> c_default_pointer_mode may need to be applied when
> build_pointer_type() is called.  I don't recall off-hand
> when these situations came up, but it might be easy enough
> to put some assertions in build_pointer_type() and then
> run the "C" test suite and see what turns up.

I think we should discuss these cases.  From my current understanding, these
direct calls that affect you are currently bugs.

Once I completed the VMS patch submission, I would add some tests to check
the handling of pointer modes.

> Thus, I wonder if it might not be best to generalize
> build_pointer_type() instead of introducing c_build_pointer_type()
> and dealing with any "C" specific checks (somehow) there?

I am almost sure that this is not correct.  build_pointer_type is part of the
middle end, where the 'pragma pointer_size' doesn't apply and the ptr_mode
should be used.

Tristan.
diff mbox

Patch

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