[Return to Library] [Contents] [Previous Chapter] [Next Section] [Next Chapter] [Index] [Help]


3    Pragma Preprocessor Directives

This chapter describes the implementation-specific pragmas that are supported on the C compiler:

All of these pragmas can be used with the -newc or -migrate flags. A subset of these pragmas can be used with the -oldc flag:

#pragma function
#pragma intrinsic
#pragma pack
#pragma pointer_size
#pragma weak


[Return to Library] [Contents] [Previous Chapter] [Next Section] [Next Chapter] [Index] [Help]


3.1    The #pragma environment Directive

The C compiler (using the -newc flag) supports a #pragma environment directive that allows you to set, save, and restore the state of all context pragmas. The context pragmas are:

#pragma member_alignment
#pragma message
#pragma pack
#pragma pointer_size

A context pragma can save and restore previous states, usually before and after including a header file that might also use the same type of pragma.

The #pragma environment directive protects include files from compilation contexts set by encompassing programs, and protects encompassing programs from contexts set in header files that they include.

This pragma has the following syntax:

#pragma environment [ command_line | header_defaults | restore | save ]

command_line
Sets the states of all of the context pragmas set on the command line. You can use this pragma to protect header files from environment pragmas that take effect before the header file is included.

header_defaults
Sets the states of all of the context pragmas to their default values. This is equivalent to the situation in which a program with no command-line options and no pragmas is compiled, except that this pragma sets the pragma message state to #pragma nostandard, as is appropriate for header files.

restore
Restores the current state of every context pragma.

save
Saves the current state of every context pragma.

Without requiring further changes to the source code, you can use #pragma environment to protect header files from things like language enhancements that might introduce additional compilation contexts.

A header file can selectively inherit the state of a pragma from the including file and then use additional pragmas as needed to set the compilation to nondefault states. For example:

#ifdef _ _pragma_environment
#pragma _ _environment save  [1]
#pragma _ _environment header_defaults [2]
#pragma member_alignment restore [3]
#pragma member_alignment save [4]
#endif
.
.    /*contents of header file*/
.
#ifdef _ _pragma_environment
#pragma _ _environment restore
#endif

In this example:

  1. Saves the state of all context pragmas. [Return to example]

  2. Sets the default compilation environment. [Return to example]

  3. Pops the member alignment context from the
    #pragma member_alignment stack that was pushed by
    #pragma _ _environment  save and restoring the member alignment context to its pre-existing state. [Return to example]

  4. Pushes the member alignment context back onto the stack so that the #pragma _ _environment  restore can pop the entry. [Return to example]

Therefore, the header file is protected from all pragmas, except for the member alignment context that the header file was meant to inherit.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


3.2    The #pragma inline Directive

Function inlining (supported by the C compiler using the -newc flag) is the inline expansion of function calls, replacing the function call with the function code itself. Inline expansion of functions reduces execution time by eliminating function-call overhead and allowing the compiler's general optimization methods to apply across the expanded code. Compared with the use of function-like macros, function inlining has the following advantages:

The C compiler (using the -newc flag) enables the following preprocessor directives to control function inlining:

#pragma inline ( id, . . . )
#pragma noinline ( id, . . . )

Where id is a function identifier.

If a function is named in a #pragma inline directive, calls to that function are expanded as inline code, if possible. If a function is named in a #pragma noinline directive, calls to that function are not expanded as inline code. If a function is named in both a #pragma inline and a #pragma noinline directive, an error message is issued.

If a function is to be expanded inline, you must place the function definition in the same module as the function call. The definition can appear either before or after the function call.

The cc command flags -O4 (for -oldc), -O3 and -O4 (for -newc),
-inline size, -inline speed, or -inline all cause the compiler to attempt to expand calls to functions named in neither a #pragma inline nor a #pragma noinline directive as inline code whenever appropriate, as determined by the following function characteristics:

For optimization level -O2, the C compiler (using the -newc flag) inlines small static routines only.

The use of the #pragma inline directive causes inline expansion regardless of the size or number of times the specified functions are called.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


3.3    The #pragma intrinsic and #pragma function Directives

Certain functions can be declared to be intrinsic. Intrinsic functions are functions for which the C compiler generates optimized code in certain situations, possibly avoiding a function call.

Table 3-1 shows the functions that can be declared to be intrinsic.

Table 3-1: Intrinsic Functions

abs fabs labs
printf fprintf sprintf
strcpy memcpy memmove
memset alloca bcopy
bzero    

To control whether a function is treated as an intrinsic, use one of the following pragmas (where func_name_list is a comma-separated list of function names optionally enclosed in parentheses):

#pragma intrinsic [ ( ] func_name_list [ ) ]
#pragma function [ ( ] func_name_list [ ) ]
#pragma function ( )

The intrinsic pragma enables intrinsic treatment of a function. When the intrinsic pragma is turned on, the compiler understands how the functions work, thereby generating more efficient code. A declaration for the function must be in effect at the time the pragma is processed.

The function pragma disables the intrinsic treatment of a function. A function pragma with an empty func_name_list disables intrinsic processing for all functions.

Some standard library functions also have built-in counterparts in the compiler. A built-in is a synonym name for the function and is equivalent to declaring the function to be intrinsic. The following built-ins (and their built-in names) are provided:

Function Synonym
abs _ _builtin_abs 
labs _ _builtin_labs 
fabs _ _builtin_fabs 
alloca _ _builtin_alloca 
strcpy _ _builtin_strcpy 

Several methods are available for using intrinsics and built-ins. The header files containing the declarations of the functions contain the intrinsic pragma for the functions shown in Table 3-1. To enable the pragma, you must define the preprocessor macro _INTRINSICS. For alloca, all that is necessary is to include alloca.h.

For example, to get the intrinsic version of abs, a program should include stdlib.h and compile with -D_INTRINSICS, or define _INTRINSICS with a #define directive before including stdlib.h.

To enable built-in processing, use the -D switch. For example, to enable the fabs built-in, the proc.c program is compiled with one of the following:

cc -Dfabs=_ _builtin_fabs prog.c

cc -Dabs=_ _builtin_abs prog.c

Optimization of the preceding functions varies according to the function and how it is used:


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


3.4    The #pragma linkage Directive

The C compiler (using the -newc flag) supports a #pragma linkage directive that allows you to specify linkage types. A linkage type specifies how a function uses a set of registers. It allows you to specify the registers that a function uses. It also allows you to specify the characteristics of a function (for example, the registers in which it passes parameters or returns values) and the registers that it can modify. The #pragma use_linkage directive associates a previously defined linkage with a function (see Section 3.9).

The #pragma linkage directive affects both the call site and function compilation (if the function is written in C). If the function is written in assembler, you can use "linkage pragma" to describe how the assembler uses registers.

The #pragma linkage directive has the following format:

#pragma linkage linkage-name = (characteristics)

linkage-name
Identifies the linkage type being defined. It has the form of a C identifier. Linkage types have their own name space, so their names will not conflict with other identifiers or keywords in the compilation unit.


characteristics
Specifies information about where parameters will be passed, where the results of the function are to be received, and what registers are modified by the function call.

You must specify a register-list. A register-list is a comma-separated list of register names, either Rn or Fn. A register-list can also contain parenthesized sublists. Use the register-list to describe arguments and function result types that are structures, where each member of the structure is passed in a single register. For example:

parameters (r0, (f0, f1))

The preceding example is a function with two parameters. The first parameter is passed in R0. The second parameter is a structure type with two floating-point members, which are passed in F0 and F1.

The following list of characteristics can be specified as a parenthesized list of comma-separated items. Note, these keywords can be supplied in any order.

The #pragma linkage directive does not support structures containing nested substructures as parameters or function return types with special linkages. Functions that have a special linkage associated with them do not support parameters or return types that have a union type.

The following characteristics specify a simple-register-list containing two elements (registers F3 and F4); and a register-list containing two elements (the register R0 and a sublist containing the registers F0 and F1):

nopreserve(f3, f4)
parameters(r0, (f0, f1))

The following example shows a linkage using such characteristics:

#pragma linkage my_link=(nopreserve(f3,f4),
                parameters(r0,(f0,f1)),
                notneeded (lp))

The parenthesized notation in a register-list describes arguments and function return values of type struct, where each member of the struct is passed in a single register. In the following example, sample_linkage specifies two parameters - the first is passed in registers R0, R1, and R2 and the second is passed in F1:

struct sample_struct_t {
    int A, B;
    short C;
    } sample_struct;

 
#pragma linkage sample_linkage = (parameters ((r0, r1, r2), f1)) void sub (struct sample_struct_t p1, double p2) { }
 
main() { double d;
 
sub (sample_struct, d); }


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


3.5    The #pragma member_alignment Directive

By default, the compiler aligns structure members on natural boundaries. Use the #pragma [no] member_alignment {specifier} preprocessor directive (supported by the C compiler using the -newc flag) to determine the byte alignment of structure members.

This pragma has the following formats:

#pragma member_alignment [ save | restore ]
#pragma nomember_alignment

Use #pragma member_alignment to specify natural-boundary alignment of structure members. When #pragma member_alignment is used, the compiler aligns structure members on the next boundary appropriate to the type of the member, rather than on the next byte. For instance, an int variable is aligned on the next longword boundary; a short variable is aligned on the next word boundary.

Where the #pragma [no] member_alignment directives allow you to choose between natural and byte alignment, the pragma pack directive allows you to specify structure member alignment on byte, word, longword, or quadword boundaries. See Section 3.7 for more information on #pragma pack.

With any combination of #pragma member_alignment, #pragma nomember_alignment, and #pragma pack, each pragma remains in effect until the next one is encountered.

The #pragma member_alignment save and #pragma member_alignment restore directives can be used to save the current state of the member_alignment (including pack alignment) and to restore the previous state, respectively. The ability to control the state is necessary for writing header files that require member_alignment or nomember_alignment, or that require inclusion in a member_alignment that is already set.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


3.6    The #pragma message Directive

The #pragma message directive (supported by the C compiler using the -newc flag) controls the issuance of individual diagnostic messages or groups of diagnostic messages. The use of this pragma overrides any command-line flags that may affect the issuance of messages.

The #pragma message directive has the following formats:

#pragma message [ enable | disable ] (message-list)
#pragma message [ save | restore ]

enable | disable message-list


save | restore

The save and restore flags are useful primarily within header files.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


3.7    The #pragma pack Directive

The C compiler uses the pack pragma to change the alignment restrictions on all members of the structure. The pack pragma must come prior to the entire structure definition because it acts on the whole structure. The syntax of this pragma is as follows:

#pragma pack ( n)

The n is a number (such as 1, 2, or 4) that specifies that subsequent structure members be aligned on n-byte boundaries. If you supply a value of 0 (zero) for n, the alignment reverts to the default, which may have been set by the -Zpn flag to the cc command.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


3.8    The #pragma pointer_size Directive

This directive controls pointer size allocation for the following:

This pragma has the following syntax:

#pragma pointer_size { long | short | 64 | 32 } | { restore | save }

The keywords long and 64 set all pointer sizes as 64-bits in all declarations that follow this directive, until the compiler encounters another #pragma pointer_size directive.

The keywords short and 32 set all pointer sizes as 32-bits in declarations that follow this directive, until the compiler encounters another #pragma pointer_size directive.

The save keyword saves the current pointer size and the restore keyword restores the saved pointer size. The save and restore options are particularly useful for specifying mixed pointer support and for protecting header files that interface to older objects. Objects compiled with multiple pointer size pragmas will not be compatible with old objects, and the compiler cannot discern that incompatible objects are being mixed.

The use of short pointers is restricted to DEC C++ and the C compilers resident on Digital UNIX. Programs should not attempt to pass short pointers from C++ routines to routines written in any language other than the C programming language. Also, DEC C++ may require explicit conversion of short pointers to long pointers in applications that use short pointers. You should first port those applications in which you are considering using short pointers, and then analyze them to determine if short pointers would be beneficial. A difference in the size of a pointer in a function declaration is not sufficient to overload a function.

The C compiler (using the -newc flag) issues an error level diagnostic if it encounters any of the following conditions:


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


3.9    The #pragma use_linkage Directive

After defining a special linkage with the #pragma linkage directive, as described in Section 3.4, use the #pragma use_linkage directive (supported by the C compiler using the -newc flag) to associate the linkage with a function.

This pragma has the following format:

#pragma use_linkage linkage-name (routine1, routine2, ...)

linkage-name
This is the name of a linkage previously defined by the #pragma linkage directive.

routine1, routine2, ...
These are the names of functions that you want associated with the specified linkage.

The #pragma use_linkage directive must appear in the source file before any use or definition of the specified routines. Otherwise, the results are unpredictable.

The following example defines a special linkage and associates it with a routine that takes three integer parameters and returns a single integer result in the same location where the first parameter was passed:

#pragma linkage example_linkage (parameters(r16, r17, r19), result(r16))
#pragma use_linkage example_linkage (sub)
int sub (int p1, int p2, short p3);

 
main() { int result;
 
result = sub (1, 2, 3); }

In this example, the result (r16) option indicates that the function result will be returned in R16 instead of the usual location (R0). The parameters option indicates that the three parameters passed to sub should be passed in R16, R17, and R19.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Chapter] [Index] [Help]


3.10    The #pragma weak Directive

The C compiler uses the weak pragma to define a new weak external symbol and associates this new symbol with an external symbol. The syntax for this pragma is as follows:

#pragma weak ( secondary-name, primary-name)

See Section 2.8 for information on strong and weak symbols.