2. Using the tiarmclang Compiler and Linker

2.1. Using the Compiler and Linker

Both the TI Arm Clang (tiarmclang) Compiler Tools’ compiler and linker can be invoked from the tiarmclang command-line. The following subsections describe the basics of how to manage the compile and link steps of building an application from the tiarmclang command-line.

2.1.1. Compiling and Linking

The default behavior of the tiarmclang compiler is to compile specified C, C++, or assembly source files into temporary object files, and then pass those object files along with any explicitly specified object files and any specified linker options to the linker.

tiarmclang [options] [source file names] [object file names] [-Wl,<linker options>]

In the following example, assume that the C code in file1.c references a data object that is defined in an object file named file2.o. The specified tiarmclang command compiles file1.c into a temporary object file. That object file, along with file2.o and a linker command file, link_test.cmd, are sent to the linker and linked with applicable object files from the tiarmclang runtime libraries to create an executable output file named test.out:

tiarmclang -mcpu=cortex-m0 file1.c file2.o -o test.out -Wl,link_test.cmd

Note that there is no mention of the tiarmclang runtime libraries on the tiarmclang command-line or inside the link_test.cmd linker command file. When the linker is invoked from the tiarmclang command-line, the tiarmclang compiler implicitly tells the linker where to find applicable runtime libraries, such as the C runtime library (libc.a).

In the above tiarmclang command-line, the -Wl, prefix in front of the specification of the link_test.cmd file name indicates to the compiler that the link_test.cmd file should be sent directly to the TI linker (you can also use the -Xlinker prefix for this purpose).

2.1.2. Compiling and Linking with Verbose Linker Output

If you add the verbose (-v) option to the above tiarmclang command, you will see exactly how the linker (tiarmlnk) is invoked and with what options. For example, this command:

tiarmclang -mcpu=cortex-m0 -v file1.c file2.o -o test.out -Wl,link_test.cmd

shows the following with regards to how the tiarmlnk command is invoked by the tiarmclang compiler:

<install directory>/bin/tiarmlnk -I<install directory>/lib
-o test.out /tmp/file1-98472f.o file2.o link_test.cmd
--start-group -llibc++.a -llibc++abi.a -llibc.a -llibsys.a
-llibsysbm.a -llibclang_rt.builtins.a -llibclang_rt.profile.a --end-group

In the above invocation of the linker, the compiler inserts a -I<install directory>/lib option, which tells the linker where to find the tiarmclang runtime libraries. The compiler also inserts the --start_group/--end_group option list, which specifies exactly which runtime libraries to incorporate into the link.

2.1.3. Compiling Only

You can avoid invoking the linker by specifying the -c option on the tiarmclang command-line.

tiarmclang -c [options] [source file names]

The following example generates object files file1.o and file2.o from the C files file1.c and file2.c, respectively:

tiarmclang -c -mcpu=cortex-m0 file1.c file2.c

Using the -S option causes the compiler to generate assembly files from the C or C++ source files that are specified on the command-line. When -S is specified on the command-line, compilation stops after the assembly files are emitted, preventing the compiler from generating an object file or invoking the linker.

tiarmclang -S [options] [source file names]

The following example generates assembly files, file1.s and file2.s, each containing GNU-syntax Arm assembly language directives and instructions:

tiarmclang -S -mcpu=cortex-m0 file1.c file2.c

2.2. Useful Compiler Options

The commonly used options listed in the subsections below are available on the tiarmclang compiler command-line.

2.2.1. Processor Options

  • -mcpu - select the target processor version

The tiarmclang compiler supports the following Arm Cortex-M processor variants which support 16-bit and T32 THUMB instructions (as indicated):

  • -mcpu=cortex-m0 - 16-bit THUMB

  • -mcpu=cortex-m0plus - 16-bit THUMB

  • -mcpu=cortex-m3 - T32 THUMB

  • -mcpu=cortex-m4 - T32 THUMB

The tiarmclang compiler also supports Arm Cortex-R type processor variants, Cortex-R4 and Cortex-R5, which can execute ARM and T32 THUMB instructions. By default, the tiarmclang compiler assumes ARM instruction mode, but the user can instruct the compiler to assume the use of T32 THUMB instructions for a given compilation by specifying the -mthumb option.

  • -mcpu=cortex-r4 - ARM (default) and/or T32 THUMB

  • -mcpu=cortex-r5 - ARM (default) and/or T32 THUMB

If an -mcpu variant is not specified on the tiarmclang command-line, then the compiler assumes a default of -mcpu=cortex-m4.

2.2.2. Instruction Mode Options

The Cortex-M type Arm processors only support execution of THUMB mode instructions, so -mthumb is selected by default when using the -mcpu=cortex-m0, -mcpu=cortex-m0plus, -mcpu=cortex-m3, or -mcpu=cortex-m4 processor options.

  • -mthumb - select THUMB mode instructions (16-bit THUMB or T32 THUMB depending on which processor variant is selected) for current compilation; default for Cortex-M type architectures

Cortex-R type Arm processors can execute both ARM and T32 THUMB mode instructions. When either the -mcpu=cortex-r4 or -mcpu=cortex-r5 processor option is specified on the command-line, the tiarmclang compiler assumes ARM instruction mode by default. This can be overridden for a given compilation by specifying the -mthumb option in combination with -mcpu=cortex-r4 or -mcpu=cortex-r5 to cause the compiler to generate T32 THUMB instructions.

  • -marm - select ARM mode instructions for current compilation; default for Cortex-R type processors

2.2.3. Endianness

All of the Arm Cortex-M type processor variants supported by the tiarmclang compiler are little-endian. The Arm Cortex-R type processor variants supported by the tiarmclang compiler may be big-endian or little-endian. The following options can be used to select the endian-ness to be assumed for a given compilation:

  • -mlittle-endian - select little-endian; default

  • -mbig-endian - select big-endian; only applicable for Cortex-R

2.2.4. Floating-Point Support Options

Some Arm processor variants can be used in conjunction with floating-point hardware to perform floating-point operations more efficiently. To enable this support, specify the -mfloat-abi=hard option in combination with the appropriate -mfpu option depending on what Arm processor variant is in use.

  • -mfloat-abi= - select floating point ABI

    • hard - floating-point hardware is available; select appropriate hardware with -mfpu option

    • soft - unless -mfloat-abi=hard is selected, floating-point operations are emulated in software

  • -mfpu= - select floating-point hardware

    Only certain Arm processor variants can be used in conjunction with floating-point hardware processors. The cortex-m0, cortex-m0plus, and cortex-m3 Arm processor variants are not compatible with any floating-point hardware processor.

    • vfpv3-d16 - available in combination with -mcpu=cortex-r4 or -mcpu=cortex-r5

    • fpv4-sp-d16 - available in combination with -mcpu=cortex-m4

2.2.5. Include Options

The tiarmclang compiler utilizes the include file directory search path to locate header files that are included by a C/C++ source file via #include preprocessor directives. The tiarmclang compiler implicitly defines an initial include file directory search path to contain directories relative to the tools installation area where C/C++ standard header files can be found. These C/C++ standard header files are considered part of the tiarmclang compiler package and should be used in combination with linker and the runtime libraries that are included in the tiarmclang compiler tools installation.

  • -I<dir>

    The -I option allows you to add your own directories to the include file directory path, allowing user-created header files to be easily accessible during compilation.

2.2.6. Predefined Symbol Options

In addition to the pre-defined macro symbols that the tiarmclang compiler defines depending on which processor options are selected, you can also manage your own symbols at compile-time using the -D and -U options. These options are useful when the source code is configured to behave differently based on whether a compile-time symbol is defined and/or what value it has.

  • -D<name>[=<value>]

    A user-created pre-defined compile symbol can be defined and given a value using the -D option. In the following example, MySym is defined and given a value 123 at compile-time. MySym will then be available for use during the compilation of the test.c source file.

tiarmclang -mcpu=cortex-m0 -DMySym=123 -c test.c
  • -U<name>

    The -U option can be used to cancel a previous definition of a specified <name> whether it was pre-defined implicitly by the compiler or with a prior -D option.

2.2.7. Optimization Options

To enable optimization passes in the tiarmclang compiler, select a level of optimization from among the following -O[0|1|2|3|fast|g|s|z] options. In general, the options below represent various levels of optimization with some options designed to favor smaller compiler-generated code size over performance, while others favor performance at the cost of increased compiler-generated code size.

Among the options listed below, -Oz is recommended as the optimization option to use if small compiler-generated code size is a priority for an application. Using -Oz retains performance gains from many of the -O2 level optimizations that are performed.

  • -O0 - No optimization. This setting is not recommended, because it can make debugging difficult.

  • -O1 or -O - Restricted optimizations, providing a good trade-off between code size and debuggability.

  • -O2 - Most optimizations enabled; some optimizations that require significant additional compile time are disabled.

  • -O3 - All optimizations available at -O2 plus others that require additional compile time to perform.

  • -Ofast - All optimizations available at -O3 plus additional aggressive optimizations with potential for additional performance gains, but also not guaranteed to be in strict compliance with language standards.

  • -Og - Restricted optimizations while preserving debuggability. All optimizations available at -O1 are performed with the addition of some optimizations from -O2.

  • -Os - All optimizations available at -O2 plus additional optimizations that are designed to reduce code size while mitigating negative impacts on performance.

  • -Oz - All optimizations available at -O2 plus additional optimizations to further reduce code size with the risk of sacrificing performance.

Note

Optimization Option Recommendations:

  • The -O1 option is recommended for maximum debuggability.

  • The -Oz option is recommended for optimizing code size.

  • The -O3 option is recommended for optimizing performance, but it is likely to increase compiler-generated code size.

2.2.8. Debug Options

The tiarmclang compiler generates DWARF debug information when the -g or -gdwarf-3 option is selected.

  • -g or -gdwarf-3 - emit DWARF version 3 debug information

2.2.9. Control Options

Some tiarmclang compiler options can be used to halt compilation at different stages:

  • -c - stop compilation after emitting compiler-generated object files; do not call linker

  • -E - stop compilation after the pre-processing phase of the compiler; this option can be used in conjunction with several other options that provide further control over the pre-processor output:

    • -dD - print macro definitions in addition to normal preprocessor output

    • -dI - print include directives in addition to normal preprocessor output

    • -dM - print macro symbol definitions instead of normal preprocessor output

  • -S - stop compilations after emitting compiler-generated assembly files; do not call assembler or linker

2.2.10. Compiler Output Option

  • -o<file>

    The -o option names the output file that results from a tiarmclang command. If tiarmclang is used to compile and link an executable output file, then the -o option’s <file> argument names that output file. If no -o option is specified in a compile and link invocation of tiarmclang then the linker will produce an executable output file named a.out.

    If the compiler is used to process a single source file, then the -o option will name the output of the compilation. This is sometimes useful in case there is a need to name the output file from the compiler something other than what the compiler will produce by default. In the following example, the output object file from the compilation of C source file task_42.c is named task.o by the -o option, replacing the task_42.o that would normally be generated by the compiler:

tiarmclang -mcpu=cortex-m0 -c task_42.c -o task.o

2.2.11. Source File Interpretation Option

The tiarmclang compiler interprets source files with a recognized file extension in a predictable manner. The recognized file extensions include:

  • .c - C source file

  • .C or .cpp - C++ source file

  • .s - GNU-syntax Arm assembly source file

  • .S - GNU-syntax Arm assembly source file to be preprocessed by the compiler

The tiarmclang compiler also supports a -x <language> option that permits you to dictate how subsequent input files on the command-line are to be treated by the compiler. This can be used to override default file extension interpretations or to instruct the compiler how to interpret a file extension that is not automatically recognized by the compiler. The following <language> types are available with the -x option:

  • -x none - reset compiler to default file extension interpretation

  • -x c - interpret subsequent input files as C source files

  • -x c++ - interpret subsequent input files as C++ source files

  • -x assembler - interpret subsequent files as GNU-syntax Arm assembly source files

  • -x assembler-with-cpp - interpret subsequent files as GNU-syntax Arm assembly source files that will be preprocessed by the compiler

  • -x ti-asm - interpret subsequent source files as legacy TI-syntax assembly source files causing the compiler to invoke the legacy TI-syntax Arm assembler to process them. For more information about handling legacy TI-syntax Arm assembly source files, please see Invoking the TI-Syntax ARM Assembler from tiarmclang.

Note

The -x<language> option is position-dependent. A given -x option on the tiarmclang command-line will be in effect until the end of the command-line or until a subsequent -x option is encountered on the command-line.

2.3. Linker Options

2.3.2. Basic Linker Options

Listed below are some of the basic options that are commonly used when invoking the linker. They can be specified on the command-line or inside of a linker command file. The tiarmclang tool’s linker is nearly identical to the linker in the legacy TI compiler toolchain. You can find more information about linker options in Linker Options.

  • --map_file=<file> or -m<file> - emit information about the result of a link into the specified map <file>

  • --output_file=<file> or -o<file> - emit linked output to specified <file>

  • --args_size=<size> or --args=<size> - reserve <size> bytes of space to store command-line arguments that are passed to the linked application

  • --heap_size=<size> or --heap=<size> - reserve <size> bytes of heap space to be used for dynamically allocated memory

  • --stack_size=<size> or --stack=<size> - reserve <size> bytes of stack space for the run-time execution of the linked application

2.3.3. Specifying Linker Options on the tiarmclang Command-Line

As noted in a few of the above examples, when invoking the linker from the tiarmclang command, options that are to be passed directly to the linker must be preceded with a -Wl, (note that the comma is required) or -Xlinker prefix. In this example, the tiarmclang compiler passes the link_test.cmd linker command file directly to the linker:

tiarmclang -mcpu=cortex-m0 file1.c file2.o -o test.out -Wl,link_test.cmd

The tiarmclang command line provides the following ways to pass options to the linker:

  • The -Wl, option passes a comma-separated list of options to the linker. (A comma after -Wl is required.)

  • The -Xlinker option passes a single option to the linker and can be used multiple times on the same command line.

  • A linker command file can specify options to pass to the linker.

For example, the following command line passes several linker options using the -Wl, option:

tiarmclang -mcpu=cortex-m0 hello.c -o a.out -Wl,-stack=0x8000,--ram_model,link_test.cmd

The following command line passes the same linker options using the -Xlinker option instead:

tiarmclang -mcpu=cortex-m0 hello.c -o a.out -Wl,-stack=0x8000,--ram_model,link_test.cmd

The following lines from a linker command file, pass the same linker options to the linker:

/*********************************************************************/
/* Example Linker Command File                                       */
/*********************************************************************/
-stack  0x8000                  /* SOFTWARE STACK SIZE               */
--ram_model                     /* INITIALIZE VARIABLES AT LOAD TIME */

2.4. Runtime Support

2.4.1. Predefined Macro Symbols

The tiarmclang compiler pre-defines compile-time macro symbols for use in source to help distinguish code written particularly for Arm, for a specific Arm processor variant, or to be compiled by the tiarmclang compiler (as opposed to other Arm compilers) from other source code.

The tiarmclang compiler complies with the Arm C Language Extensions (ACLE) in that it will pre-define appropriate ACLE macro symbols based on the processor options specified on the tiarmclang command-line. Consider the following tiarmclang command:

tiarmclang -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -c test.c

When the tiarmclang compiler is invoked with the above command, these are some of the ACLE pre-defined macro symbols that will be defined:

__ARM_ACLE             200  - indicates compliance with ACLE
                              specification 2.0
__ARM_ARCH             7    - identifies Arm architecture level
__ARM_ARCH_ISA_THUMB   2    - indicates Thumb instruction set present
__ARM_ARCH_PROFILE     'M'  - identifies a Cortex-M type Arm architecture
__ARM_FP               0x6  - indicates floating-point hardware is available
__ARM_FP16_FORMAT_IEEE 1    - indicates 16-bit floating-point, IEEE format
__ARM_PCS              1    - using Arm procedure call standard (PCS)
__ARM_PCS_VFP          1    - indicates floating-point arguments passed in
                              floating-point hardware registers

For more information about ACLE pre-defined macro symbols, please see the Arm C Language Extensions - Release ACLE Q2 2018 specification.

In addition to the ACLE pre-defined macro symbols, the tiarmclang compiler also pre-defines several TI-specific pre-defined macro symbols that can be used to distinguish the use of the tiarmclang compiler from other Arm compilers. These include:

For a complete list of pre-defined macro symbols that are defined by the tiarmclang compiler for a given compilation, the processor options can be combined with the -E -dM preprocessor option combination. This will instruct the compiler to run only the preprocessor pass of the compilation and emit the list of pre-defined macro symbols that are defined along with their values to stdout.

2.4.2. Header Files

The header files provided with the installation of the tiarmclang compiler tools must be used when using functions from any of the runtime libraries provided with the tools installation. These include the C and C++ standard header files as well as additional header files such as arm_acle.h that help the compiler to support the Arm C Language Extensions. The tiarmclang compiler implicitly defines the initial include file directory search path so that these header files are accessible during a compilation.

2.4.3. Runtime Libraries

When linking an application containing object files that were generated by the tiarmclang compiler, the appropriate tiarmclang runtime libraries must be included in the link so that references to functions and data objects that are defined in the runtime libraries can be properly resolved at link time.

When the tiarmclang command is used to invoke the linker, the compiler implicitly defines the initial object file directory search path to contain directories relative to the tools installation area where runtime libraries can be found. The tiarmclang compiler also implicitly adds the following --start-group/--end-group option list to the linker invocation:

--start-group -llibc++.a -llibc++abi.a -llibc.a -llibsys.a
-llibsysbm.a -llibclang_rt.builtins.a -llibclang_rt.profile.a --end-group

This option list instructs the linker to search among the list of specified runtime libraries for definitions of unresolved symbol references. When a definition of a function or data object that resolves a previously unresolved reference is encountered, the section containing the definition is pulled into the link from the runtime library where it is defined. If new unresolved symbol references are introduced while this process is in progress, the libraries are re-read until no further needed definitions can be found among the --start_group/--end_group list of runtime libraries.

There are several different runtime library configurations supported in the tiarmclang compiler toolchain. An application built using the tiarmclang compiler tools must use a combination of target options that is compatible with one of the following configurations:

Note

C++ Exceptions

Support for C++ exceptions is off by default. You can specify the -fexceptions option on the tiarmclang command-line to enable exceptions. If -fexceptions is specified on the tiarmclang command-line, then the linker will link the application with a runtime support library that was built with C++ exceptions enabled.

2.4.3.1. Cortex-M Configurations

  • armv6m-ti-none-eabi: (cortex-m0 or cortex-m0plus), little-endian

    The tiarmclang compiler supports generating execute-only code for Cortex-M0/M0+ Arm processor variants. This feature is off by default, but can be enabled using the -mexecute-only compiler option. If the -mexecute-only option is specified on the tiarmclang command-line, then the linker will link the application with a Cortex-M0/M0+ runtime library that was built with the execute-only feature enabled.

    • execute-only off (default)

    • execute-only on

  • armv7m-ti-none-eabi: cortex-m3, little-endian

  • armv7em-ti-none-eabi: cortex-m4, little-endian

  • armv7em-ti-none-eabihf: cortex-m4, fpv4-sp-d16 fpu (default), little-endian

  • armv8m.main-ti-none-eabi: cortex-m33, little-endian

  • armv8m.main-ti-none-eabihf: cortex-m33, fpv5-sp-d16 fpu (default), little-endian

2.4.3.2. Cortex-R Configurations

Note

The Cortex-R runtime libraries included with the tiarmclang toolchain are built in ARM mode, but are compatible with Cortex-R object files that have been built with THUMB mode T32 instructions.

  • armv7r-ti-none-eabi: (cortex-r4 or cortex-r5), ARM mode, little-endian (default)

  • armv7r-ti-none-eabihf: (cortex-r4 or cortex-r5), ARM mode, vfpv3-d16 (default for cortex-r5), little-endian (default)

  • armv7reb-ti-none-eabi: (cortex-r4 or cortex-r5), ARM mode, big-endian

  • armv7reb-ti-none-eabhf: (cortex-r4 or cortex-r5), ARM mode, vfpv3-d16 (default for cortex-r5), big-endian

Note

If you are building an application with target options that are not compatible with any of the above configurations, you will encounter a link-time error in which the linker is unable to locate a compatible version of a runtime library in order to successfully complete the link. If this happens, and the configuration is valid for a TI device, please report the issue on the TI E2E™ design community and select the device being used.

For the compile options used in each of these configurations, refer to Processor Variants Supported by tiarmclang.