Keil Logo

Technical Support

On-Line Manuals

Compiler Reference Guide

Preface Arm Compiler Tools Overview armclang Reference armclang Command-line Options Summary of armclang command-line options -C (armclang) -c (armclang) -D (armclang) -E -e -fbare-metal-pie -fbracket-depth=N -fcommon, -fno-common -fdata-sections, -fno-data-sections -ffast-math, -fno-fast-math -ffixed-rN -ffp-mode -ffunction-sections, -fno-function-sections -fident, -fno-ident @file -fldm-stm, -fno-ldm-stm -fno-builtin -fno-inline-functions -flto, -fno-lto -fexceptions, -fno-exceptions -fomit-frame-pointer, -fno-omit-frame-pointer -fpic, -fno-pic -fropi, -fno-ropi -fropi-lowering, -fno-ropi-lowering -frwpi, -fno-rwpi -frwpi-lowering, -fno-rwpi-lowering -fsanitize -fshort-enums, -fno-short-enums -fshort-wchar, -fno-short-wchar -fstack-protector, -fstack-protector-all, -fstack- -fstrict-aliasing, -fno-strict-aliasing -fsysv, -fno-sysv -ftrapv -fvectorize, -fno-vectorize -fvisibility -fwrapv -g, -gdwarf-2, -gdwarf-3, -gdwarf-4 (armclang) -I -include -L -l -M, -MM -MD, -MMD -MF -MG -MP -MT -march -marm -masm -mbig-endian -mbranch-protection -mcmodel -mcmse -mcpu -mexecute-only -mfloat-abi -mfpu -mimplicit-it -mlittle-endian -mno-neg-immediates -moutline, -mno-outline -mpixolib -munaligned-access, -mno-unaligned-access -mthumb -nostdlib -nostdlibinc -O (armclang) -o (armclang) -pedantic -pedantic-errors -Rpass -S (armclang) -save-temps -shared (armclang) -std --target -U -u (armclang) -v (armclang) --version (armclang) --version_number (armclang) --vsn (armclang) -W (armclang) -Wl -Xlinker -x (armclang) -### Compiler-specific Keywords and Operators Compiler-specific keywords and operators __alignof__ __asm __declspec attributes __declspec(noinline) __declspec(noreturn) __declspec(nothrow) __inline __promise __unaligned Global named register variables Compiler-specific Function, Variable, and Type Att Function attributes __attribute__((always_inline)) function attribute __attribute__((cmse_nonsecure_call)) function attr __attribute__((cmse_nonsecure_entry)) function att __attribute__((const)) function attribute __attribute__((constructor(priority))) function at __attribute__((format_arg(string-index))) function __attribute__((interrupt("type"))) function attrib __attribute__((malloc)) function attribute __attribute__((naked)) function attribute __attribute__((noinline)) function attribute __attribute__((nomerge)) function attribute __attribute__((nonnull)) function attribute __attribute__((noreturn)) function attribute __attribute__((not_tail_called)) function attribut __attribute__((nothrow)) function attribute __attribute__((pcs("calling_convention"))) functio __attribute__((pure)) function attribute __attribute__((section("name"))) function attribut __attribute__((target("options"))) function attrib __attribute__((unused)) function attribute __attribute__((used)) function attribute __attribute__((value_in_regs)) function attribute __attribute__((visibility("visibility_type"))) fun __attribute__((weak)) function attribute __attribute__((weakref("target"))) function attrib Type attributes __attribute__((aligned)) type attribute __attribute__((packed)) type attribute __attribute__((transparent_union)) type attribute Variable attributes __attribute__((alias)) variable attribute __attribute__((aligned)) variable attribute __attribute__((deprecated)) variable attribute __attribute__((packed)) variable attribute __attribute__((section("name"))) variable attribut __attribute__((unused)) variable attribute __attribute__((used)) variable attribute __attribute__((visibility("visibility_type"))) var __attribute__((weak)) variable attribute __attribute__((weakref("target"))) variable attrib Compiler-specific Intrinsics __breakpoint intrinsic __current_pc intrinsic __current_sp intrinsic __disable_fiq intrinsic __disable_irq intrinsic __enable_fiq intrinsic __enable_irq intrinsic __force_stores intrinsic __memory_changed intrinsic __schedule_barrier intrinsic __semihost intrinsic __vfp_status intrinsic Compiler-specific Pragmas #pragma clang system_header #pragma clang diagnostic #pragma clang section #pragma once #pragma pack(...) #pragma unroll[(n)], #pragma unroll_completely #pragma weak symbol, #pragma weak symbol1 = symbol Other Compiler-specific Features ACLE support Predefined macros Inline functions Volatile variables Half-precision floating-point data types Half-precision floating-point number format Half-precision floating-point intrinsics Library support for _Float16 data type BFloat16 floating-point number format TT instruction intrinsics Non-secure function pointer intrinsics Supported architecture feature combinations for sp armclang Integrated Assembler Syntax of assembly files for integrated assembler Assembly expressions Alignment directives Data definition directives String definition directives Floating-point data definition directives Section directives Conditional assembly directives Macro directives Symbol binding directives Org directive AArch32 target selection directives AArch64 target selection directives Space-filling directives Type directive Integrated assembler support for the CSDB instruct armclang Inline Assembler Inline Assembly File-scope inline assembly Inline assembly statements within a function Assembly string Output and input operands Clobber list volatile Inline assembly constraint strings Constraint modifiers Constraint codes Constraint codes common to AArch32 state and AArch Constraint codes for AArch32 state Constraint codes for AArch64 state Using multiple alternative operand constraints Inline assembly template modifiers Template modifiers common to AArch32 state and AAr Template modifiers for AArch32 state Template modifiers for AArch64 state Forcing inline assembly operands into specific reg Symbol references and branches into and out of inl Duplication of labels in inline assembly statement armlink Reference fromelf Reference armar Reference armasm Legacy Assembler Reference Appendixes

Global named register variables

B2.11 Global named register variables

The compiler enables you to use the register storage class specifier to store global variables in general-purpose registers. These variables are called global named register variables.


register Type VariableName __asm("Reg")


The data type of variable. The data type can be char or any 8-bit, 16-bit, or 32-bit integer type, or their respective pointer types.
The name of the variable.
The general-purpose register to use to store the variable. The general purpose register can be R6 to R11.


This feature is only available for AArch32 state.

If you use -mpixolib, then you must not use the following registers as global named register variables:

  • R8
  • R9

If you use -frwpi or -frwpi-lowering, then you must not use register R9 as a global named register variable. If you do, then armclang throws an error.

If needed, the Arm ABI reserves the following registers for use as a frame pointer:

  • R7 in T32 state.
  • R11 in A32 state.

armclang throws an error if you use global named register variables under these conditions.

Code size

Declaring a general-purpose register as a global named register variable means that the register is not available to the compiler for other operations. If you declare too many global named register variables, code size increases significantly. Sometimes, your program might not compile, for example if there are insufficient registers available to compute a particular expression.


Using global named register variables enables faster access to these variables than if they are stored in memory.


For correct runtime behavior:

  • You must use the relevant -ffixed-rN option for all the registers that you use as a global named register variable.
  • You must use the relevant -ffixed-rN option to compile any source file that contains calls to external functions that use global named register variables.

For example, to use register R8 as a global named register for an integer foo, you must use:

register int  foo  __asm("R8")

For this example, you must compile with the command-line option -ffixed-r8. For more information, see B1.12 -ffixed-rN.

The Arm standard library has not been built with any -ffixed-rN option. If you want to link application code containing global named register variables with the Arm standard library, then:

  • To ensure correct runtime behavior, ensure that the library code does not call code that uses the global named register variables in your application code.
  • The library code might push and pop the register to stack, even if your application code uses this register as a global named register variable.


  • If you use the register storage class, then you cannot use any additional storage class such as extern, static, or typedef for the same variable.
  • In C and C++, global named register variables cannot be initialized at declaration.


The following example demonstrates the use of register variables and the relevant -ffixed-rN option.

Source file main.c contains the following code:

#include <stdio.h>

/* Function defined in another file that will be compiled with
   -ffixed-r8 -ffixed-r9. */
extern int add_ratio(int a, int b, int c, int d, int e, int f);

/* Helper variable */
int other_location = 0;

/* Named register variables */
register int foo __asm("r8");
register int *bar __asm("r9");

__attribute__((noinline))  int initialise_named_registers(void)
    /* Initialise pointer-based named register variable */
    bar = &other_location;

    /* Test using named register variables */
    foo = 1000;
    *bar = *bar + 1;
    return 0;

int main(void)
   add_ratio(10, 2, 30, 4, 50, 6);
   printf("foo: %d\n", foo);  // expects to print 1000
   printf("bar: %d\n", *bar); // expects to print 1

Source file sum.c contains the following code:

/* Arbitrary function that could normally result in the compiler using R8 and R9.
When compiling with -ffixed-r8 -ffixed-r9, the compiler must not use registers 
R8 or R9 for any function in this file.
__attribute__((noinline)) int add_ratio(int a, int b, int c, int d, int e, int f)
   int sum;
   sum = a/b + c/d + e/f;
   if (a > b && c > d)
     return sum*e*f;
     return (sum/e)/f;

Compile main.c and sum.c separately before linking them. This application uses global named register variables using R8 and R9, and therefore both source files must be compiled with the relevant -ffixed-rN option:

armclang --target=arm-arm-none-eabi -march=armv8-a -O2 -ffixed-r8 -ffixed-r9 -c main.c -o main.o --save-temps
armclang --target=arm-arm-none-eabi -march=armv8-a -O2 -ffixed-r8 -ffixed-r9 -c sum.c -o sum.o --save-temps

Link the two object files using armlink:

armlink --cpu=8-a.32 main.o sum.o -o image.axf

The use of the armclang option --save-temps enables you to look at the generated assembly code. The file sum.s is generated from sum.c, and does not use registers R8 and R9 in the add_ratio() function:

    .cfi_sections .debug_frame
@ %bb.0:
    .save    {r4, r5, r11, lr}
    push    {r4, r5, r11, lr}
    .cfi_def_cfa_offset 16
    .cfi_offset lr, -4
    .cfi_offset r11, -8
    .cfi_offset r5, -12
    .cfi_offset r4, -16
    ldr    r12, [sp, #20]
    sdiv    r4, r2, r3
    ldr    lr, [sp, #16]
    sdiv    r5, r0, r1
    add    r4, r4, r5
    cmp    r0, r1
    sdiv    r5, lr, r12
    cmpgt    r2, r3
    add    r4, r4, r5
    bgt    .LBB0_2
@ %bb.1:
    sdiv    r0, r4, lr
    sdiv    r0, r0, r12
    pop    {r4, r5, r11, pc}
    mul    r0, r12, lr
    mul    r0, r0, r4
    pop    {r4, r5, r11, pc}

The file main.s has been generated from main.c, and uses registers R8 and R9 only for the code that directly uses these global named register variables:

    .cfi_sections .debug_frame
@ %bb.0:
    movw    r9, :lower16:other_location
    mov    r8, #1000
    movt    r9, :upper16:other_location
    ldr    r0, [r9]
    add    r0, r0, #1
    str    r0, [r9]
    mov    r0, #0
    bx    lr
@ %bb.0:
    .save    {r11, lr}
    push    {r11, lr}
    .cfi_def_cfa_offset 8
    .cfi_offset lr, -4
    .cfi_offset r11, -8
    .pad    #8
    sub    sp, sp, #8
    .cfi_def_cfa_offset 16
    bl    initialise_named_registers
    mov    r0, #6
    mov    r1, #50
    str    r1, [sp]
    mov    r1, #2
    str    r0, [sp, #4]
    mov    r0, #10
    mov    r2, #30
    mov    r3, #4
    bl    add_ratio
    adr    r0, .LCPI1_0
    mov    r1, r8
    bl    __2printf
    ldr    r1, [r9]
    adr    r0, .LCPI1_1
    bl    __2printf
    mov    r0, #0
    add    sp, sp, #8
    pop    {r11, pc}
    .p2align    2


The Arm standard library code, such as the library implementations for the printf() function, might still use R8 and R9 because the standard library has not been built with any -ffixed-rN option.
Non-ConfidentialPDF file icon PDF version101754_0616_01_en
Copyright © 2019–2021 Arm Limited or its affiliates. All rights reserved. 
  Arm logo
Important information

This site uses cookies to store information on your computer. By continuing to use our site, you consent to our cookies.

Change Settings

Privacy Policy Update

Arm’s Privacy Policy has been updated. By continuing to use our site, you consent to Arm’s Privacy Policy. Please review our Privacy Policy to learn more about our collection, use and transfers
of your data.