Adding 64 Bit Pointer Support To 32 Bit Runtime Library
Adding 64 Bit Pointer Support To 32 Bit Runtime Library
Smith
A key component of delivering 64-bit addressing The OpenVMS Alpha operating system, version 7.0,
on the OpenVMS Alpha operating system, ver- has extended the address space accessible to applica-
sion 7.0, is an enhanced C run-time library that tions beyond the traditional 32-bit address space. This
new address space is referred to as 64-bit virtual mem-
allows application programmers to allocate and
ory and requires a 64-bit pointer for memory access.1
utilize 64-bit virtual memory from their C pro- The operating system has an additional set of new
grams. This C run-time library includes modified memory allocation routines that allows programs to
programming interfaces and additional new allocate and release 64-bit memory. In OpenVMS
interfaces yet ensures upward compatibility Alpha version 7.0, this set of routines is the only mech-
for existing applications. The same run-time anism available to acquire 64-bit memory.
For application programs to take advantage of these
library supports applications that use only
new OpenVMS programming interfaces, high-level
32-bit addresses, only 64-bit addresses, or programming languages such as C had to support
a combination of both. Source code changes 64-bit pointers. Both the C compiler and the C run-
are not required to utilize 64-bit addresses, time library required changes to provide this support.
although recompilation is necessary. The new The compiler needed to understand both 32-bit and
techniques used to analyze and modify the 64-bit pointers, and the run-time library needed to
accept and return such pointers.
interfaces are not specific to the C run-time
The compiler has a new qualifier called /pointer_size,
library and can serve as a guide for engineers which sets the default pointer size for the compilation
who are enhancing their programming inter- to either 32 bits or 64 bits. Also added to the compiler
faces to support 64-bit pointers. are pragmas (directives) that can be used within the
source code to change the active pointer size. An
application program is not required to compile each
module using the same /pointer_size qualifier; some
modules may use 32-bit pointers while others use
64-bit pointers. Benson, Noel, and Peterson describe
these compiler enhancements.2 The DEC C User’s
Guide for OpenVMS Systems documents the qualifier
and the pragmas.3
The C run-time library added 64-bit pointer sup-
port either by modifying the existing interface to a
function or by adding a second interface to the same
function. Public header files define the C run-time
library interfaces. These header files contain the pub-
licly accessible function prototypes and structure defi-
nitions. The library documentation and header files
are shipped with the C compiler; the C run-time
library ships with the operating system.
This paper discusses all phases of the enhancements
to the C run-time library, from project concepts
through the analysis, the design, and finally the imple-
mentation. The DEC C Runtime Library Reference
Manual for OpenVMS Systems contains user documen-
tation regarding the changes.4
#ifndef __HEADER_LOADED
#define __HEADER_LOADED 1
#ifndef __SIZE_T
# define __SIZE_T 1
typedef unsigned int size_t;
#endif
#endif /* __HEADER_LOADED */
Figure 1
Original Header File <header.h>
/*
** Ensure that we begin with 32-bit pointers.
*/
#if __INITIAL_POINTER_SIZE
# if (__VMS_VER < 70000000)
# error "Pointer size added in OpenVMS V7.0 for Alpha“
# endif
# pragma __pointer_size __save
# pragma __pointer_size 32
#endif
/*
** STRUCTURES NOT AFFECTED BY POINTERS
*/
#ifndef __SIZE_T
# define __SIZE_T 1
typedef unsigned int size_t;
#endif
/*
** FUNCTIONS THAT NEED 64-BIT SUPPORT
*/
int execv(const char *, char *[]);
void free(void *);
void *malloc(size_t);
char *strcat(char *, const char *);
char *strerror(int);
size_t strlen(const char *);
/*
** Create 32-bit header file typedefs.
*/
/*
** Create 64-bit header file typedefs.
*/
/*
** FUNCTIONS RESTRICTED FROM 64 BITS
*/
/*
** Change default to 64-bit pointers.
*/
#if __INITIAL_POINTER_SIZE
# pragma __pointer_size 64
#endif
/*
** FUNCTIONS THAT SUPPORT 64-BIT POINTERS
*/
int rand(void);
/*
** Restore the user’s pointer context.
*/
#if __INITIAL_POINTER_SIZE
# pragma __pointer_size __restore
#endif
#endif /* __HEADER_LOADED */
Figure 2
First Pass through <header.h>
/*
** This include file defines all 32-bit and 64-bit data types used in
** the implementation of 64-bit addresses in the C run-time library.
**
** Those modules that are compiled with a 64-bit-capable compiler
** are required to enable pointer size with /POINTER_SIZE=32.
*/
#ifdef __INITIAL_POINTER_SIZE
# if (__INITIAL_POINTER_SIZE != 32)
# error “This module must be compiled /pointer_size=32”
# endif
#endif
/*
** All interfaces that require 64-bit pointers must use one of
** the following definitions. When this header file is used on
** platforms not supporting 64-bit pointers, these definitions
** will define 32-bit pointers.
*/
#ifdef __INITIAL_POINTER_SIZE
# pragma __pointer_size __save
# pragma __pointer_size 64
#endif
#include <curses.h>
typedef WINDOW *__wide_WINDOW_ptr;
#include <string.h>
typedef size_t *__wide_size_t_ptr;
/*
** Restore pointer size.
*/
#ifdef __INITIAL_POINTER_SIZE
# pragma __pointer_size __restore
#endif
Figure 3
Typedefs from <wide_types.src>
# include <builtins.h>
# define C$$IS_SHORT_ADDR(addr) \
((((__int64)(addr)<<32)>>32) == (unsigned __int64)addr)
# define C$$SHORT_ADDR_OF_STRING(addr) \
(C$$IS_SHORT_ADDR(addr) ? (char *) (addr) \
:(char *) strcpy(__ALLOCA(strlen(addr) + 1), (addr)))
# define C$$SHORT_ADDR_OF_STRUCT(addr) \
(C$$IS_SHORT_ADDR(addr) ? (void *) (addr) \
:(void *) memcpy(__ALLOCA(sizeof(* addr)), (addr), sizeof(*addr)))
#else
#endif
Figure 4
Macros from <wide_types.src>
Implementing the strerror Return Pointer The private header file typedefs are always declared
The function strerror always returns a 32-bit pointer. starting with two underscores and ending in either
The memory is allocated by the C run-time library for “_ptr32” or “_ptr64.” These typedefs are created only
both 32-bit and 64-bit calling programs. As shown when the header file needs to be in a particular
in Figure 5, we moved the function strerror into the pointer-size mode while referring to a pointer of the
section “Functions that support 64-bit pointers” of other size. The return value of strerror is modified to
<header.h> to show that there are no restrictions on use the typedef __char_ptr32.
the use of this function. Including the header file, which declares strerror,
The “Create 32-bit header file typedefs” section of allows the compiler to verify that the arguments,
<header.h> is in the 32-bit pointer section, where the return values, and pointer sizes are correct.
bound-to-low-memory data structures are declared.
The function returns a pointer to a character string. Widening the strlen Argument
We, therefore, added typedefs for __char_ptr32 and The function strlen accepts a constant character
__const_char_ptr32 while in a 32-bit pointer context. pointer and returns an unsigned integer (size_t).
These declarations are protected with the definition of Implementing full 64-bit support in strlen means
__CHAR _ PTR32 to allow multiple header files to use changing the parameter to a 64-bit constant character
the same naming convention. Declarations of the pointer. If an application passes a 32-bit pointer to
const form of the typedef are always made in the same the strlen function, the compiler-generated code sign
conditional code since they usually are needed and extends the pointer. The required header file mod-
using the same condition removes the need for a dif- ification is to simply move strlen from the sec-
ferent protecting name. tion “Functions that need 64-bit support” to the
The strerror function could have been implemented section “Functions that support 64-bit pointers.”
in <header.h> by placing the function in the 32-bit sec- The steps necessary for the source code to support
tion, but that would have implied that the 32-bit 64-bit addressing are as follows:
pointer was a restriction that could be removed later.
1. Ensure that the module includes header files that
The pointer is not a restriction, and the strerror func-
declare strlen.
tion fully supports 64-bit pointers.
/*
** Ensure that we begin with 32-bit pointers.
*/
#if __INITIAL_POINTER_SIZE
# if (__VMS_VER < 70000000)
# error ”Pointer size added in OpenVMS V7.0 for Alpha“
# endif
# pragma __pointer_size __save
# pragma __pointer_size 32
#endif
/*
** STRUCTURES NOT AFFECTED BY POINTERS
*/
#ifndef __SIZE_T
# define __SIZE_T 1
typedef unsigned int size_t;
#endif
/*
** FUNCTIONS THAT NEED 64-BIT SUPPORT
*/
/*
** Create 32-bit header file typedefs.
*/
#ifndef __CHAR_PTR32
# define __CHAR_PTR32 1
typedef char *__char_ptr32;
typedef const char *__const_char_ptr32;
#endif
/*
** Create 64-bit header file typedefs.
*/
#ifndef __CHAR_PTR64
# define __CHAR_PTR64 1
# pragma __pointer_size 64
typedef char *__char_ptr64;
typedef const char *__const_char_ptr64;
# pragma __pointer_size 32
#endif
/*
** FUNCTIONS RESTRICTED FROM 64 BITS
*/
int execv(__const_char_ptr64, char *[]);
/*
** Change default to 64-bit pointers.
*/
#if __INITIAL_POINTER_SIZE
# pragma __pointer_size 64
#endif
/*
** The following functions have interfaces of XXX, _XXX32,
** and _XXX64.
**
** The function strcat has two interfaces because the return
** argument is a pointer that is relative to the first arguments.
**
** The malloc function returns either a 32-bit or a 64-bit
** memory address.
*/
#if __INITIAL_POINTER_SIZE == 32
# pragma __pointer_size 32
#endif
Figure 5
Final Form of <header.h>
#if __INITIAL_POINTER_SIZE == 32
# pragma __pointer_size 64
#endif
#endif
/*
** FUNCTIONS THAT SUPPORT 64-BIT POINTERS
*/
void free(void *__ptr);
int rand(void);
size_t strlen(const char *__s);
/*
** Restore the user’s pointer context.
*/
#if __INITIAL_POINTER_SIZE
# pragma __pointer_size __restore
#endif
#endif /* __HEADER_LOADED */
Figure 5
Continued
2. Add the following line of code to the top of the Initially, the execv function was to have had two
module: #include <wide_types.src>. implementations. The parameters passed to the execv
3. Change the declaration of the function to accept function are used as the parameters to the main func-
a __wide_const_char_ptr parameter instead of the tion of the child process being started. Because no
previous const char * parameter. assumptions could be made about that child process
(in terms of support for 64-bit pointers), these para-
4. Visually follow this argument through the code,
meters are restricted to low memory addresses.
looking for assignment statements. This particular
To illustrate that the argv passing was a restriction,
function would be a simple loop. If local variables
we place that prototype into the section “Functions
store this pointer, they must also be declared as
restricted from 64 bits” of <header.h>. The first argu-
__wide_const_char_ptr.
ment, the name of the file, did not need to have this
5. Compile the source code using the directive restriction. The section “Create 64-bit header file
/warn=enable=maylosedata to have the compiler typedefs” was enhanced to add the definition of
help detect pointer truncation. __const_char_ptr64, which allows the prototypes to
6. Add a new test to the test system to exercise 64-bit define a 64-bit pointer to constant characters while in
pointers. either 32-bit or 64-bit context.
#include <string.h>
#include <wide_types.src>
/*
** STRCAT/_STRCAT64
**
** The ‘strcat’ function concatenates ‘s2’, including the
** terminating null character, to the end of ‘s1’.
*/
Figure 6
Implementation of 32-bit and 64-bit strcat Functions
References
Biography
Duane A. Smith
As a consulting software engineer, Duane Smith is currently
architect and project leader of the C run-time library for
the OpenVMS VAX and Alpha platforms. He joined Digital
in 1981 and has worked on a variety of projects, including
the A-to-Z Database Manager and the Language-Sensitive
Editor. Duane received his B.S. in engineering from the
University of Connecticut in 1981 and his M.S. in soft-
ware engineering from Wang Institute of Graduate Studies
in 1987. He pursued his master’s degree through Digital’s
Graduate Engineering Education Program (GEEP). Duane
holds one U.S. patent issued for the DECwindows Structured
Visual Navigation (SVN) widget.