A short-form pragma given without a digit resets that pragma to its default state; otherwise to the state specified.
#pragma -LetterOptional digit
#pragma [no]feature-name
For example:
The list of recognised pragmas is:
#pragma -s1
#pragma nocheck_stack
#pragma -p2
#pragma profile_statements
--------------------------------------------------------- Pragma Name |Short Form |`no' Form --------------------------------------------------------- warn_implicit_fn_decls |a1 * |a0 --------------------------------------------------------- check_memory_accesses |c1 |c0 * --------------------------------------------------------- warn_deprecated |d1 * |d0 --------------------------------------------------------- continue_after_hash_error |e1 |e0 * --------------------------------------------------------- FP register variable |f1-f4 |f0 * --------------------------------------------------------- include_only_once |i1 |i0 * --------------------------------------------------------- optimise_crossjump |j1 * |j0 --------------------------------------------------------- optimise_multiple_loads |m1 * |m0 --------------------------------------------------------- profile |p1 |p0 * --------------------------------------------------------- profile_statements |p2 |p0 * --------------------------------------------------------- integer register variable |r1-r7 |r0 * --------------------------------------------------------- check_stack |s0 * |s1 --------------------------------------------------------- force_top_level |t1 |t0 * --------------------------------------------------------- check_printf_formats |v1 |v0 * --------------------------------------------------------- check_scanf_formats |v2 |v0 * --------------------------------------------------------- side_effects |y0 * |y1 --------------------------------------------------------- optimise_cse |z1 * |z0 ---------------------------------------------------------
In each case, the default setting is starred.
Certain of the pragmas give more local control over what can be controlled per compilation unit, from the command line. For example:
-zpLetterDigit
-------------------------------------------------------- Pragma Name |Command Line Form -------------------------------------------------------- nowarn_implicit_fn_decls |-Wf -------------------------------------------------------- nowarn_deprecated |-Wd -------------------------------------------------------- profile |-p -------------------------------------------------------- profile_statements |-px --------------------------------------------------------
Pragma force_top_level asserts that the containing #include file should only be included at the top level of a file. A syntax error will result if the file is included, say, within the body of a function.
By default, functions are assumed to be impure, so function invocations are not candidates for common subexpression elimination. Pragma noside_effects asserts that the following function declarations (until the next #pragma side_effects) describe pure functions, invocations of which can be CSEs. See also __pure.
Pragmas Controlling Code Generation
The pragma check_memory_accesses instructs the compiler to precede each access to memory by a call to the appropriate one of:
It is up to your library implementation to check that the address given is reasonable.
__rt_rd?chk (?=1,2,4 for byte, short, long reads, respectively)
__rt_wr?chk (?=1,2,4 for byte, short, long writes, respectively)
The pragmas f0-f4 and r0-r7 have no long form counterparts. Each introduces or terminates a list of extern, file-scope variable declarations. Each such declaration declares a name for the same register variable. For example:
Any type that can be allocated to a register (see Registers), can be allocated to a global register. Similarly, any floating point type can be allocated to a floating point register variable.
#pragma r1 /* 1st global register */
extern int *sp;
#pragma r2 /* 2nd global register */
extern int *fp, *ap; /* synonyms */
#pragma r0 /* end of global declaration */
#pragma f1
extern double pi; /* 1st global FP register */
#pragma f0
Global register r1 is the same as register v1 in the ARM Procedure Call Standard (APCS); similarly r2 equates to v2, etc. Depending on the APCS variant, between 5 and 7 integer registers (v1-v7, machine registers R4-R10) and 4 floating point registers (F4-F7) are available as register variables. In practice it is probably unwise to use more than 3 global integer register variables and 2 global floating-point register variables.
Provided the same declarations are made in each separate compilation unit, a global register variable may exist program-wide.
Otherwise, because a global register variable maps to a callee-saved register, its value will be saved and restored across a call to a function in a compilation unit which does not use it as a global register variable, such as a library function.
A corollary of the safety of direct calls out of a global-register-using compilation unit, is that calls back into it are dangerous. In particular, a global-register-using function called from a compilation unit which uses that register as a compiler-allocated register, will probably read the wrong values from its supposed global register variables.
Currently, there is no link-time check that direct calls are sensible. And even if there were, indirect calls via function arguments pose a hazard which is harder to detect. This facility must be used with care. Preferably, the declaration of the global register variable should be made in each compilation unit of the program. See also __global_reg(n).
See ARM Procedure Call Standard for details of the default way in which structures are passed and returned.
typedef struct int64_structt {
unsigned int lo;
unsigned int hi;
} int64;
__value_in_regs extern int64 mul64(unsigned a, unsigned b);
for example
void __swi(swi_number) swi_name(int arg1, ..., int argn);
For a swi returning 1 result, use:
void __swi(42) terminate_process(int arg1, ..., int argn);
For a swi returning more than 1 result
int __swi(swi_number) swi_name(int arg1, ..., int argn);
Note that __value_in_regs is needed to specify that a (short) structure value is returned in registers, rather than by the usual indirection mechanism specified in the ARM Procedure Call Standard.
struct { int res1, ... resn }
__value_in_regs
__swi(swi_number) swi_name(int arg1, ... int argn);
If there is an indirect SWI (taking the number of a SWI to call as an argument in r12), calls through this SWI can similarly be described by a C function declaration such as:
For example,
int __swi_indirect(swi_indirect_number)
swi_name(int real_swi_number, int arg1, ... argn);
This might be called as:
int __swi_indirect(0) ioctl(int swino, int fn, void *argp);
ioctl(IOCTL+4, RESET, NULL);
__pure
By default, functions are assumed to be impure (ie they have side effects), so function invocations are not candidates for common subexpression elimination. __pure has the same effect as pragma noside_effects, and asserts that the function declared is a pure function, invocations of which can be CSEs.
Note that the global register, whether specified by keyword or pragmas, musr be specified in all declarations of the same variable. Thus
is an error.
int x;
__global_reg(1) x;