This chapter describes the implementation-specific pragmas that are supported on the C compiler:
#pragma
environment
(Section 3.1)
#pragma
inline
(Section 3.2)
#pragma
intrinsic
and
#pragma
function
(Section 3.3)
#pragma
linkage
(Section 3.4)
#pragma
member_alignment
(Section 3.5)
#pragma
message
(Section 3.6)
#pragma
pack
(Section 3.7)
#pragma
pointer_size
(Section 3.8)
#pragma
use_linkage
(Section 3.9)
#pragma
weak
(Section 3.10)
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
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
header_defaults
#pragma
nostandard
,
as is appropriate for header files.
restore
save
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:
#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]
#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.
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:
struct
argument. An argument that is a
pointer to a
struct
is not restricted.
varargs
or
stdarg
package to access the function's arguments because
they require arguments to be in adjacent memory
locations, and inline expansion may violate that requirement.
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.
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.
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:
abs
fabs
labs
alloca
The function call overhead is removed.
printf
and
fprintf
functions are converted to call
puts
,
putc
,
fputs
,
or
fputc
or their equivalents, depending on the format string and the
number and types of arguments.
sprintf
function is inlined or converted to a call to
strcpy
.
strcpy
function is inlined if the source string (the second argument)
is a string literal.
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
characteristics
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.
parameters
(register-list
)
The
parameters
characteristic passes arguments to a routine in specific registers.
Each item in the
register-list
describes one parameter that is passed to the routine.
You can pass structure arguments by value, with the restriction that each member of the structure is passed in a separate parameter location. Doing so, however, may produce code that is slower because of the large number of registers used. The compiler does not diagnose this condition.
Valid registers for the
parameters
option include integer registers R0 through R25 and floating-point
registers F0 through F30.
Structure types require at least one register for each field. The compiler verifies that the number of registers required for a structure type is the same as the number provided in the pragma.
result
(register-list
)
The compiler needs to know which registers will be used to return the
value from the function. Use the
result
characteristic to pass this information.
If a function does not return a value (that is, the function has a
return type of
void)
,
do not specify
result
as part of the linkage.
Valid registers for the
register
option include general-purpose registers R0
through R25 and floating-point registers F0 through F30.
preserved
(register-list
)
nopreserve
(register-list
)
notused
(register-list
)
notneeded
((lp))
The compiler needs to know which registers are used by the function
and which are not, and of those used, whether they are preserved
across the function call. To specify this information, use the
preserved
,
nopreserve
,
notused
,
and
notneeded
options:
preserved
register contains the same value after a call to the function as it
did before the call.
nopreserve
register does not necessarily contain the same value after a call to
the function as it did before the call.
notused
register is not used in any way by the called function.
notneeded
characteristic indicates that certain items are not needed by the
routines using this linkage.
The
lp
keyword specifies that the Linkage Pointer register (R27) does not
need to be set up when calling the specified functions.
The linkage pointer is required when the called function accesses
global or
static
data. You must determine whether it is valid to specify that the
register is not needed.
Valid registers for the
preserved
,
nopreserve
,
and
notused
options include general-purpose registers R0 through R30, and
floating-point registers F0 through F30.
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); }
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.
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
enable
- Enables issuance of the messages specified in the message list.
disable
- Disables issuance of the messages specified in the message
list.
message-list
The
message-list
can be one of the following:
-verbose
flag on the
cc
command to obtain the message identifier.
ALL
- Messages in the compiler
CHECK
- Messages about potentially poor coding practices
PORTABLE
- Messages about portability
Only messages of severity Warning or Information can be disabled. If the message has severity of Error or Fatal, it is issued regardless of any attempt to disable it.
The default is to issue all diagnostic messages for the
selected compiler mode except those in the
CHECK
group, which must be explicitly enabled to display its messages.
save | restore
save
- Saves the current state of which messages are
enabled and disabled.
restore
- Restores the previous state of which messages
are enabled and disabled.
The
save
and
restore
flags are useful primarily within header files.
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.
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:
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
#pragma
linkage
directive.
routine1
,
routine2
,
...
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.
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.