6 TMS320C6000C/C++ Language Implementation. Texas Instruments TMS320C6000 Optimizing Compiler v 6.1 (Rev. O), TMS320C6000 Optimizing Compiler v 7.4 (Rev. U), TMS320C6000 Optimizing Compiler v 7.0 (Rev. Q), TMS320C6000 Optimizing Compiler v 6.0 Beta (Rev. N)
تبلیغات
تبلیغات
Chapter 6
SPRU187U – July 2012
TMS320C6000C/C++ Language Implementation
The C/C++ compiler supports the C/C++ language standard that was developed by a committee of the
American National Standards Institute (ANSI) and subsequently adopted by the International Standards
Organization (IS0).
The C++ language supported by the C6000 is defined by the ANSI/ISO/IEC 14882:1998 standard with certain exceptions.
Topic
...........................................................................................................................
Page
6.1
Characteristics of TMS320C6000 C ....................................................................
6.2
Characteristics of TMS320C6000 C++ .................................................................
6.3
Using MISRA-C:2004 ........................................................................................
6.4
Data Types
6.5
Keywords
......................................................................................................
.......................................................................................................
6.6
C++ Exception Handling ...................................................................................
6.7
Register Variables and Parameters ....................................................................
6.8
The asm Statement
6.9
Pragma Directives
..........................................................................................
...........................................................................................
6.10
The _Pragma Operator .....................................................................................
6.11
Application Binary Interface ..............................................................................
6.12
Object File Symbol Naming Conventions (Linknames) .........................................
6.13
Initializing Static and Global Variables in COFF ABI Mode ....................................
6.14
Changing the ANSI/ISO C Language Mode ..........................................................
6.15
GNU Language Extensions ...............................................................................
146 TMS320C6000C/C++ Language Implementation
Copyright © 2012, Texas Instruments Incorporated
SPRU187U – July 2012
Submit Documentation Feedback
www.ti.com
Characteristics of TMS320C6000 C
6.1
Characteristics of TMS320C6000 C
The compiler supports the C language as defined by ISO/IEC 9899:1990, which is equivalent to American
National Standard for Information Systems-Programming Language C X3.159-1989 standard, commonly referred to as C89, published by the American National Standards Institute. The compiler can also accept many of the language extensions found in the GNU C compiler (see
). The compiler does not support C99.
The ANSI/ISO standard identifies some features of the C language that are affected by characteristics of the target processor, run-time environment, or host environment. For reasons of efficiency or practicality, this set of features can differ among standard compilers.
Unsupported features of the C library are:
• The run-time library has minimal support for wide and multi-byte characters. The type wchar_t is implemented as int. The wide character set is equivalent to the set of values of type char. The library includes the header files <wchar.h> and <wctype.h>, but does not include all the functions specified in the standard. So-called multi-byte characters are limited to single characters. There are no shift states.
The mapping between multi-byte characters and wide characters is simple equivalence; that is, each wide character maps to and from exactly a single multi-byte character having the same value.
• The run-time library includes the header file <locale.h>, but with a minimal implementation. The only supported locale is the C locale. That is, library behavior that is specified to vary by locale is hardcoded to the behavior of the C locale, and attempting to install a different locale by way of a call to setlocale() will return NULL.
6.2
Characteristics of TMS320C6000 C++
The C6000 compiler supports C++ as defined in the ANSI/ISO/IEC 14882:1998 standard, including these features:
• Complete C++ standard library support, with exceptions noted below.
• Templates
• Exceptions, which are enabled with the --exceptions option; see
• Run-time type information (RTTI), which can be enabled with the --rtti compiler option.
The exceptions to the standard are as follows:
• The compiler does not support embedded C++ run-time-support libraries.
• The library supports wide chars (wchar_t), in that template functions and classes that are defined for char are also available for wchar_t. For example, wide char stream classes wios, wiostream, wstreambuf and so on (corresponding to char classes ios, iostream, streambuf) are implemented.
However, there is no low-level file I/O for wide chars. Also, the C library interface to wide char support
(through the C++ headers <cwchar> and <cwctype>) is limited as described above in the C library.
• For COFF ABI only: If the definition of an inline function contains a static variable, and it appears in multiple compilation units (usually because it’s a member function of a class defined in a header file), the compiler generates multiple copies of the static variable rather than resolving them to a single definition. The compiler emits a warning (#1369) in such cases.
• No support for bad_cast or bad_type_id is included in the typeinfo header.
• Two-phase name binding in templates, as described in [tesp.res] and [temp.dep] of the standard, is not implemented.
• The export keyword for templates is not implemented.
• A typedef of a function type cannot include member function cv-qualifiers.
• A partial specialization of a class member template cannot be added outside of the class definition.
SPRU187U – July 2012
Submit Documentation Feedback
TMS320C6000C/C++ Language Implementation
Copyright © 2012, Texas Instruments Incorporated
147
Using MISRA-C:2004 www.ti.com
6.3
Using MISRA-C:2004
You can alter your code to work with the MISRA-C:2004 rules. The following enable/disable the rules:
• The --check_misra option enables checking of the specified MISRA-C:2004 rules.
• The CHECK_MISRA pragma enables/disables MISRA-C:2004 rules at the source level. This pragma is equivalent to using the --check_misra option. See
.
• RESET_MISRA pragma resets the specified MISRA-C:2004 rules to the state they were before any
CHECK_MISRA pragmas were processed. See
.
The syntax of the option and pragmas is:
--check_misra={all|required|advisory|none|rulespec}
#pragma CHECK_MISRA ("{all|required|advisory|none|rulespec}");
#pragma RESET_MISRA ("{all|required|advisory|rulespec}");
The rulespec parameter is a comma-separated list of these specifiers:
[-]X
[-]X-Z
Enable (or disable) all rules in topic X.
Enable (or disable) all rules in topics X through Z.
[-]X.A
Enable (or disable) rule A in topic X.
[-]X.A-C Enable (or disable) rules A through C in topic X.
Example: --check_misra=1-5,-1.1,7.2-4
• Checks topics 1 through 5
• Disables rule 1.1 (all other rules from topic 1 remain enabled)
• Checks rules 2 through 4 in topic 7
Two options control the severity of certain MISRA-C:2004 rules:
• The --misra_required option sets the diagnostic severity for required MISRA-C:2004 rules.
• The --misra_advisory option sets the diagnostic severity for advisory MISRA-C:2004 rules.
The syntax for these options is:
--misra_advisory={error|warning|remark|suppress}
--misra_required={error|warning|remark|suppress}
148 TMS320C6000C/C++ Language Implementation
Copyright © 2012, Texas Instruments Incorporated
SPRU187U – July 2012
Submit Documentation Feedback
www.ti.com
Data Types
6.4
Data Types
lists the size, representation, and range of each scalar data type for the C6000 compiler for
COFF ABI. See
for the EABI data types. Many of the range values are available as standard macros in the header file limits.h.
Type char, signed char unsigned char short unsigned short int, signed int unsigned int long, signed long unsigned long
__int40_t unsigned __int40_t long long, signed long long unsigned long long enum float double
64 bits
64 bits
32 bits
32 bits
64 bits long double 64 bits
(1) pointers, references, pointer to 32 bits data members
Figures are minimum precision.
Size
8 bits
8 bits
16 bits
16 bits
32 bits
32 bits
40 bits
40 bits
40 bits
40 bits
Table 6-1. TMS320C6000 C/C++ COFF ABI Data Types
Representation Minimum
ASCII -128
ASCII
2s complement
0
-32 768
Binary
2s complement
Binary
2s complement
Binary
2s complement
Binary
0
-2 147 483 648
0
-549 755 813 888
0
-549 755 813 888
0
2s complement
Binary
2s complement
IEEE 32-bit
IEEE 64-bit
IEEE 64-bit
Binary
-9 223 372 036 854 775 808
0
-2 147 483 648
1.175 494e-38 (1)
2.22 507 385e-308
(1)
2.22 507 385e-308
(1)
0
Range
Maximum
127
255
32 767
65 535
2 147 483 647
4 294 967 295
549 755 813 887
1 099 511 627 775
549 755 813 887
1 099 511 627 775
9 223 372 036 854 775 807
18 446 744 073 709 551 615
2 147 483 647
3.40 282 346e+38
1.79 769 313e+308
1.79 769 313e+308
0xFFFFFFFF
Type char, signed char unsigned char short unsigned short int, signed int unsigned int long, signed long unsigned long
__int40_t unsigned __int40_t long long, signed long long unsigned long long enum float
40 bits
64 bits
64 bits
32 bits
32 bits double 64 bits
(1) long double 64 bits pointers, references, pointer to 32 bits data members
Figures are minimum precision.
Size
8 bits
8 bits
16 bits
16 bits
32 bits
32 bits
32 bits
32 bits
40 bits
Table 6-2. TMS320C6000 C/C++ EABI Data Types
Representation Minimum
ASCII
ASCII
-128
0
2s complement
Binary
-32 768
0
2s complement
Binary
2s complement
Binary
2s complement
-2 147 483 648
0
-2 147 483 648
0
-549 755 813 888
Binary
2s complement
Binary
2s complement
IEEE 32-bit
IEEE 64-bit
IEEE 64-bit
Binary
0
-9 223 372 036 854 775 808
0
-2 147 483 648
1.175 494e-38
(1)
2.22 507 385e-308
(1)
2.22 507 385e-308
(1)
0
Range
Maximum
127
255
32 767
65 535
2 147 483 647
4 294 967 295
2 147 483 647
4 294 967 295
549 755 813 887
1 099 511 627 775
9 223 372 036 854 775 807
18 446 744 073 709 551 615
2 147 483 647
3.40 282 346e+38
1.79 769 313e+308
1.79 769 313e+308
0xFFFFFFFF
SPRU187U – July 2012
Submit Documentation Feedback
TMS320C6000C/C++ Language Implementation 149
Copyright © 2012, Texas Instruments Incorporated
Keywords www.ti.com
6.5
Keywords
The C6000 C/C++ compiler supports the standard const, register, restrict, and volatile keywords. In addition, the C/C++ compiler extends the C/C++ language through the support of the cregister, interrupt, near, and far keywords.
6.5.1 The const Keyword
The C/C++ compiler supports the ANSI/ISO standard keyword const. This keyword gives you greater optimization and control over allocation of storage for certain data objects. You can apply the const qualifier to the definition of any variable or array to ensure that its value is not altered.
If you define an object as far const, the .const section allocates storage for the object. The const data storage allocation rule has two exceptions:
• If the keyword volatile is also specified in the definition of an object (for example, volatile const int x).
Volatile keywords are assumed to be allocated to RAM. (The program does not modify a const volatile object, but something external to the program might.)
• If the object has automatic storage (allocated on the stack).
In both cases, the storage for the object is the same as if the const keyword were not used.
The placement of the const keyword within a definition is important. For example, the first statement below defines a constant pointer p to a variable int. The second statement defines a variable pointer q to a constant int: int * const p = &x; const int * q = &x;
Using the const keyword, you can define large constant tables and allocate them into system ROM. For example, to allocate a ROM table, you could use the following definition: far const int digits[] = {0,1,2,3,4,5,6,7,8,9};
6.5.2 The cregister Keyword
The compiler extends the C/C++ language by adding the cregister keyword to allow high level language access to control registers.
When you use the cregister keyword on an object, the compiler compares the name of the object to a list of standard control registers for the C6000 (see
Table 6-3 ). If the name matches, the compiler generates
the code to reference the control register. If the name does not match, the compiler issues an error.
Register
AMR
CSR
DESR
DETR
DNUM
ECR
EFR
FADCR
FAUCR
FMCR
GFPGFR
GPLYA
CPLYB
ICR
IER
IERR
Table 6-3. Valid Control Registers
Description
Addressing mode register
Control status register
(C6700+ only) dMAX event status register
(C6700+ only) dMAX event trigger register
(C6400+ only) DSP core number register
(C6400+ only) Exception clear register
(C6400+ only) Exception flag register
(C6700 only) Floating-point adder configuration register
(C6700 only) Floating-point auxiliary configuration register
(C6700 only) Floating-point multiplier configuration register
(C6400 only) Galois field polynomial generator function register
(C6400+ only) GMPY A-side polynomial register
(C6400+ only) GMPY B-side polynomial register
Interrupt clear register
Interrupt enable register
(C6400+ only) Internal exception report register
150 TMS320C6000C/C++ Language Implementation
Copyright © 2012, Texas Instruments Incorporated
SPRU187U – July 2012
Submit Documentation Feedback
www.ti.com
Keywords
Register
IFR
ILC
IRP
ISR
ISTP
ITSR
NRP
NTSR
REP
RILC
SSR
TSCH
TSCL
TSR
Table 6-3. Valid Control Registers (continued)
Description
Interrupt flag register. (IFR is read only.)
(C6400+ only) Inner loop count register
Interrupt return pointer
Interrupt set register
Interrupt service table pointer
(C6400+ only) Interrupt task state register
Nonmaskable interrupt return pointer
(C6400+ only) NMI/exception task state register
(C6400+ only) Restricted entry point address register
(C6400+ only) Reload inner loop count register
(C6400+ only) Saturation status register
(C6400+ only) Time-stamp counter (high 32) register
(C6400+ only) Time-stamp counter (low 32) register
(C6400+ only) Task state register
The cregister keyword can be used only in file scope. The cregister keyword is not allowed on any declaration within the boundaries of a function. It can only be used on objects of type integer or pointer.
The cregister keyword is not allowed on objects of any floating-point type or on any structure or union objects.
The cregister keyword does not imply that the object is volatile. If the control register being referenced is volatile (that is, can be modified by some external control), then the object must be declared with the volatile keyword also.
To use the control registers in
, you must declare each register as follows. The c6x.h include file defines all the control registers through this syntax:
extern cregister volatile unsigned int register ;
Once you have declared the register, you can use the register name directly. See the TMS320C62x DSP
CPU and Instruction Set Reference Guide, TMS320C64x/C64x+ DSP CPU and Instruction Set Reference
Guide, the TMS320C67x/C67x+ DSP CPU and Instruction Set Reference Guide, or TMS320C66x+ DSP
CPU and Instruction Set Reference Guide for detailed information on the control registers.
See
for an example that declares and uses control registers.
Example 6-1. Define and Use Control Registers extern cregister volatile unsigned int AMR; extern cregister volatile unsigned int CSR; extern cregister volatile unsigned int IFR; extern cregister volatile unsigned int ISR; extern cregister volatile unsigned int ICR; extern cregister volatile unsigned int IER; extern cregister volatile unsigned int FADCR; extern cregister volatile unsigned int FAUCR; extern cregister volatile unsigned int FMCR; main()
{ printf("AMR = %x\n", AMR);
}
SPRU187U – July 2012
Submit Documentation Feedback
TMS320C6000C/C++ Language Implementation
Copyright © 2012, Texas Instruments Incorporated
151
Keywords www.ti.com
6.5.3 The interrupt Keyword
The compiler extends the C/C++ language by adding the interrupt keyword, which specifies that a function is treated as an interrupt function.
Functions that handle interrupts follow special register-saving rules and a special return sequence. The implementation stresses safety. The interrupt routine does not assume that the C run-time conventions for the various CPU register and status bits are in effect; instead, it re-establishes any values assumed by the run-time environment. When C/C++ code is interrupted, the interrupt routine must preserve the contents of all machine registers that are used by the routine or by any function called by the routine. When you use the interrupt keyword with the definition of the function, the compiler generates register saves based on the rules for interrupt functions and the special return sequence for interrupts.
You can only use the interrupt keyword with a function that is defined to return void and that has no parameters. The body of the interrupt function can have local variables and is free to use the stack or global variables. For example: interrupt void int_handler()
{ unsigned int flags;
...
}
The name c_int00 is the C/C++ entry point. This name is reserved for the system reset interrupt. This special interrupt routine initializes the system and calls the function main. Because it has no caller, c_int00 does not save any registers.
Use the alternate keyword, __interrupt, if you are writing code for strict ANSI/ISO mode (using the -strict_ansi compiler option).
HWI Objects and the interrupt Keyword
NOTE: The interrupt keyword must not be used when BIOS HWI objects are used in conjunction with C functions. The HWI_enter/HWI_exit macros and the HWI dispatcher contain this functionality, and the use of the C modifier can cause negative results.
6.5.4 The near and far Keywords
The C6000 C/C++ compiler extends the C/C++ language with the near and far keywords to specify how global and static variables are accessed and how functions are called.
Syntactically, the near and far keywords are treated as storage class modifiers. They can appear before, after, or in between the storage class specifiers and types. With the exception of near and far, two storage class modifiers cannot be used together in a single declaration. The following examples are legal combinations of near and far with other storage class modifiers: far static int x; static near int x; static int far x; far int foo(); static far int foo();
6.5.4.1
near and far Data Objects
Global and static data objects can be accessed in the following two ways:
152 near keyword far keyword
The compiler assumes that the data item can be accessed relative to the data page pointer. For example:
LDW *+dp(_address),a0
The compiler cannot access the data item via the DP. This can be required if the total amount of program data is larger than the offset allowed (32K) from the DP.
For example:
MVKL _address, a1
MVKH _address, a1
LDW *a1,a0
TMS320C6000C/C++ Language Implementation
Copyright © 2012, Texas Instruments Incorporated
SPRU187U – July 2012
Submit Documentation Feedback
www.ti.com
Keywords
Once a variable has been defined to be far, all external references to this variable in other C files or headers must also contain the far keyword. This is also true of the near keyword. However, you will get compiler or linker errors when the far keyword is not used everywhere. Not using the near keyword everywhere only leads to slower data access times.
If you use the DATA_SECTION pragma, the object is indicated as a far variable, and this cannot be overridden. If you reference this object in another file, then you need to use extern far when declaring this object in the other source file. This ensures access to the variable, since the variable might not be in the
.bss section. For details, see
NOTE: Defining Global Variables in Assembly Code
If you also define a global variable in assembly code with the .usect directive (where the variable is not assigned in the .bss section) or you allocate a variable into separate section using a #pragma DATA_SECTION directive; and you want to reference that variable in C code, you must declare the variable as extern far. This ensures the compiler does not try to generate an illegal access of the variable by way of the data page pointer.
When data objects do not have the near or far keyword specified, the compiler will use far accesses to aggregate data and near accesses to non-aggregate data. For more information on the data memory model and ways to control accesses to data, see
6.5.4.2
Near and far Function Calls
Function calls can be invoked in one of two ways: near keyword far keyword
The compiler assumes that destination of the call is within ± 1 M word of the caller.
Here the compiler uses the PC-relative branch instruction.
B _func
The compiler is told by you that the call is not within ± 1 M word.
MVKL _func, al
B
MVKH _func, al
_func
By default, the compiler generates small-memory model code, which means that every function call is handled as if it were declared near, unless it is actually declared far.
For more information on function calls, see
6.5.5 The restrict Keyword
To help the compiler determine memory dependencies, you can qualify a pointer, reference, or array with the restrict keyword. The restrict keyword is a type qualifier that can be applied to pointers, references, and arrays. Its use represents a guarantee by you, the programmer, that within the scope of the pointer declaration the object pointed to can be accessed only by that pointer. Any violation of this guarantee renders the program undefined. This practice helps the compiler optimize certain sections of code because aliasing information can be more easily determined.
In
the pointers a and b pointing to objects that overlap in memory. You are promising that accesses through a and b will never conflict; therefore, a write through one pointer cannot affect a read from any other pointers. The precise semantics of the restrict keyword are described in the 1999 version of the ANSI/ISO
C Standard.
SPRU187U – July 2012
Submit Documentation Feedback
TMS320C6000C/C++ Language Implementation
Copyright © 2012, Texas Instruments Incorporated
153
Keywords
Example 6-2. Use of the restrict Type Qualifier With Pointers void func1(int * restrict a, int * restrict b)
{
/* func1's code here */
} www.ti.com
illustrates using the restrict keyword when passing arrays to a function. Here, the arrays c and d should not overlap, nor should c and d point to the same array.
Example 6-3. Use of the restrict Type Qualifier With Arrays void func2(int c[restrict], int d[restrict])
{ int i;
} for(i = 0; i < 64; i++)
{ c[i] += d[i]; d[i] += 1;
}
6.5.6 The volatile Keyword
The compiler eliminates redundant memory accesses whenever possible, using data flow analysis to figure out when it is legal. However, some memory accesses may be special in some way that the compiler cannot see, and in such cases you must use the volatile keyword to prevent the compiler from optimizing away something important. The compiler does not optimize out any accesses to variables declared volatile. The number and order of accesses of a volatile variable are exactly as they appear in the C/C++ code, no more and no less.
There are different ways to understand how volatile works, but fundamentally it is a hint to the the compiler that something it cannot understand is going on, and so the compiler should not try to be overclever.
Any variable which might be modified by something external to the obvious control flow of the program
(such as an interrupt service routine) must be declared volatile. This tells the compiler that an interrupt function might modify the value at any time, so the compiler should not perform optimizations which will change the number or order of accesses of that variable. This is the primary purpose of the volatile keyword.
In the following example, the loop intends to wait for a location to be read as 0xFF: unsigned int *ctrl; while (*ctrl !=0xFF);
However, in this example, *ctrl is a loop-invariant expression, so the loop is optimized down to a singlememory read. To get the desired result, define ctrl as: volatile unsigned int *ctrl;
Here the *ctrl pointer is intended to reference a hardware location, such as an interrupt flag.
Volatile must also be used when accessing memory locations that represent memory-mapped peripheral devices. Such memory locations might change value in ways that the compiler cannot predict. These locations might change if accessed, or when some other memory location is accessed, or when some signal occurs.
Volatile must also be used for local variables in a function which calls setjmp, if the value of the local variables needs to remain valid if a longjmp occurs.
154 TMS320C6000C/C++ Language Implementation
Copyright © 2012, Texas Instruments Incorporated
SPRU187U – July 2012
Submit Documentation Feedback
www.ti.com
Example 6-4. Volatile for Local Variables With setjmp
#include <stdlib.h> jmp_buf context; void function()
{ volatile int x = 3; switch(setjmp(context))
{ case 0: setup(); break; default:
{ printf("x == %d\n", x); /* We can only reach here if longjmp has occured; because x's lifetime begins before the setjmp and lasts through the longjmp, the C standard requires x be declared "volatile" */ break;
}
}
}
C++ Exception Handling
The --interrupt_threshold=1 option should be used when compiling with volatiles.
6.6
C++ Exception Handling
The compiler supports all the C++ exception handling features as defined by the ANSI/ISO 14882 C++
Standard. More details are discussed in The C++ Programming Language, Third Edition by Bjarne
Stroustrup.
The compiler --exceptions option enables exception handling. The compiler’s default is no exception handling support.
For exceptions to work correctly, all C++ files in the application must be compiled with the --exceptions option, regardless of whether exceptions occur in a particular file. Mixing exception-enabled object files and libraries with object files and libraries that do not have exceptions enabled can lead to undefined behavior.
Exception handling requires support in the run-time-support library, which come in exception-enabled and exception-disabled forms; you must link with the correct form. When using automatic library selection (the default), the linker automatically selects the correct library
manually, you must use run-time-support libraries whose name contains _eh if you enable exceptions.
Using --exceptions causes the compiler to insert exception handling code. This code will increase the code size of the program, particularly for COFF ABI. In addition, COFF ABI will increase the execution time, even if an exception is never thrown. EABI will not increase code size as much, and has a minimal execution time cost if exceptions are never thrown, but will slightly increase the data size for the exception-handling tables.
See
for details on the run-time libraries.
6.7
Register Variables and Parameters
The C/C++ compiler treats register variables (variables defined with the register keyword) differently, depending on whether you use the --opt_level (-O) option.
• Compiling with optimization
The compiler ignores any register definitions and allocates registers to variables and temporary values by using an algorithm that makes the most efficient use of registers.
• Compiling without optimization
If you use the register keyword, you can suggest variables as candidates for allocation into registers.
The compiler uses the same set of registers for allocating temporary expression results as it uses for
SPRU187U – July 2012
Submit Documentation Feedback
TMS320C6000C/C++ Language Implementation
Copyright © 2012, Texas Instruments Incorporated
155
The asm Statement www.ti.com
allocating register variables.
The compiler attempts to honor all register definitions. If the compiler runs out of appropriate registers, it frees a register by moving its contents to memory. If you define too many objects as register variables, you limit the number of registers the compiler has for temporary expression results. This limit causes excessive movement of register contents to memory.
Any object with a scalar type (integral, floating point, or pointer) can be defined as a register variable. The register designator is ignored for objects of other types, such as arrays.
The register storage class is meaningful for parameters as well as local variables. Normally, in a function, some of the parameters are copied to a location on the stack where they are referenced during the function body. The compiler copies a register parameter to a register instead of the stack, which speeds access to the parameter within the function.
For more information about register conventions, see
6.8
The asm Statement
The C/C++ compiler can embed assembly language instructions or directives directly into the assembly language output of the compiler. This capability is an extension to the C/C++ language—the asm statement. The asm (or __asm) statement provides access to hardware features that C/C++ cannot provide. The asm statement is syntactically like a call to a function named asm, with one string constant argument:
asm(" assembler text ");
The compiler copies the argument string directly into your output file. The assembler text must be enclosed in double quotes. All the usual character string escape codes retain their definitions. For example, you can insert a .byte directive that contains quotes as follows: asm("STR: .byte \"abc\"");
The inserted code must be a legal assembly language statement. Like all assembly language statements, the line of code inside the quotes must begin with a label, a blank, a tab, or a comment (asterisk or semicolon). The compiler performs no checking on the string; if there is an error, the assembler detects it.
For more information about the assembly language statements, see the TMS320C6000 Assembly
Language Tools User's Guide.
The asm statements do not follow the syntactic restrictions of normal C/C++ statements. Each can appear as a statement or a declaration, even outside of blocks. This is useful for inserting directives at the very beginning of a compiled module.
Use the alternate statement __asm("assembler text") if you are writing code for strict ANSI/ISO C mode
(using the --strict_ansi option).
NOTE: Avoid Disrupting the C/C++ Environment With asm Statements
Be careful not to disrupt the C/C++ environment with asm statements. The compiler does not check the inserted instructions. Inserting jumps and labels into C/C++ code can cause unpredictable results in variables manipulated in or around the inserted code. Directives that change sections or otherwise affect the assembly environment can also be troublesome.
Be especially careful when you use optimization with asm statements. Although the compiler cannot remove asm statements, it can significantly rearrange the code order near them and cause undesired results.
156 TMS320C6000C/C++ Language Implementation
Copyright © 2012, Texas Instruments Incorporated
SPRU187U – July 2012
Submit Documentation Feedback
www.ti.com
Pragma Directives
6.9
Pragma Directives
Pragma directives tell the compiler how to treat a certain function, object, or section of code. The C6000
C/C++ compiler supports the following pragmas:
• CHECK_MISRA (See
)
• CLINK (See
)
• CODE_SECTION (See
)
• DATA_ALIGN (See
)
• DATA_MEM_BANK (See
• DATA_SECTION (See
• DIAG_SUPPRESS, DIAG_REMARK, DIAG_WARNING, DIAG_ERROR, and DIAG_DEFAULT (See
)
• FUNC_ALWAYS_INLINE (See
)
• FUNC_CANNOT_INLINE (See
• FUNC_EXT_CALLED (See
)
• FUNC_INTERRUPT_THRESHOLD (See
)
• FUNC_IS_PURE (See
• FUNC_IS_SYSTEM (See
• FUNC_NEVER_RETURNS (See
• FUNC_NO_GLOBAL_ASG (See
)
• FUNC_NO_IND_ASG (See
)
• FUNCTION_OPTIONS (See
• INTERRUPT (See
)
• LOCATION (See
• MUST_ITERATE (See
• NMI_INTERRUPT (See
• NOINIT (See
)
• NO_HOOKS (See
)
• PERSISTENT (See
• PROB_ITERATE (See
• RESET_MISRA (See
)
• RETAIN (See
)
• SET_CODE_SECTION (See
)
• SET_DATA_SECTION (See
• STRUCT_ALIGN (See
• UNROLL (See
)
Most of these pragmas apply to functions. Except for the DATA_MEM_BANK pragma, the arguments func and symbol cannot be defined or declared inside the body of a function. You must specify the pragma outside the body of a function; and the pragma specification must occur before any declaration, definition, or reference to the func or symbol argument. If you do not follow these rules, the compiler issues a warning and may ignore the pragma.
For the pragmas that apply to functions or symbols (except CLINK and RETAIN), the syntax for the pragmas differs between C and C++. In C, you must supply the name of the object or function to which you are applying the pragma as the first argument. In C++, the name is omitted; the pragma applies to the declaration of the object or function that follows it.
SPRU187U – July 2012
Submit Documentation Feedback
TMS320C6000C/C++ Language Implementation
Copyright © 2012, Texas Instruments Incorporated
157
Pragma Directives www.ti.com
6.9.1 The CHECK_MISRA Pragma
The CHECK_MISRA pragma enables/disables MISRA-C:2004 rules at the source level. This pragma is equivalent to using the --check_misra option.
The syntax of the pragma in C is:
#pragma CHECK_MISRA (" {all|required|advisory|none|rulespec} ");
The rulespec parameter is a comma-separated list of specifiers. See
for details.
The RESET_MISRA pragma can be used to reset any CHECK_MISRA pragmas; see
.
6.9.2 The CLINK Pragma
The CLINK pragma can be applied to a code or data symbol. It causes a .clink directive to be generated into the section that contains the definition of the symbol. The .clink directive indicates to the linker that the section is eligible for removal during conditional linking. Therefore, if the section is not referenced by any other section in the application that is being compiled and linked, it will not be included in the output file result of the link.
The syntax of the pragma in C/C++ is:
#pragma CLINK (symbol )
The RETAIN pragma has the opposite effect of the CLINK pragma. See
for more details.
6.9.3 The CODE_SECTION Pragma
The CODE_SECTION pragma allocates space for the symbol in C, or the next symbol declared in C++, in a section named section name.
The syntax of the pragma in C is:
#pragma CODE_SECTION (symbol , "section name ")
The syntax of the pragma in C++ is:
#pragma CODE_SECTION (" section name ")
The CODE_SECTION pragma is useful if you have code objects that you want to link into an area separate from the .text section.
The following examples demonstrate the use of the CODE_SECTION pragma.
Example 6-5. Using the CODE_SECTION Pragma C Source File
#pragma CODE_SECTION(fn, "my_sect") int fn(int x)
{ return x;
}
158 TMS320C6000C/C++ Language Implementation
Copyright © 2012, Texas Instruments Incorporated
SPRU187U – July 2012
Submit Documentation Feedback
www.ti.com
Example 6-6. Generated Assembly Code From
.sect
"my_sect"
.global
_fn
;******************************************************************************
;* FUNCTION NAME: _fn *
;*
;* Regs Modified
;* Regs Used
: SP
: A4,B3,SP
;* Local Frame Size : 0 Args + 4 Auto + 0 Save = 4 byte
*
*
*
*
;******************************************************************************
_fn:
;** --------------------------------------------------------------------------*
RET .S2
B3 ; |6|
SUB
STW
ADD
NOP
.D2
.D2T1
.S2
; BRANCH OCCURS
SP,8,SP
A4,*+SP(4)
8,SP,SP
2
; |4|
; |4|
; |6|
; |6|
Pragma Directives
6.9.4 The DATA_ALIGN Pragma
The DATA_ALIGN pragma aligns the symbol in C, or the next symbol declared in C++, to an alignment boundary. The alignment boundary is the maximum of the symbol's default alignment value or the value of the constant in bytes. The constant must be a power of 2.
The syntax of the pragma in C is:
#pragma DATA_ALIGN ( symbol , constant );
The syntax of the pragma in C++ is:
#pragma DATA_ALIGN ( constant );
SPRU187U – July 2012
Submit Documentation Feedback
TMS320C6000C/C++ Language Implementation
Copyright © 2012, Texas Instruments Incorporated
159
Pragma Directives www.ti.com
6.9.5 The DATA_MEM_BANK Pragma
The DATA_MEM_BANK pragma aligns a symbol or variable to a specified C6000 internal data memory bank boundary. The constant specifies a specific memory bank to start your variables on. (See
for a graphic representation of memory banks.) The value of constant depends on the C6000 device:
C6200
C6400
C6400+
C6600
C6700
C6740
The C6200 devices contain four memory banks (0, 1, 2, and 3); constant can be 0 or 2.
The C6400 devices contain 8 memory banks; constant can be 0, 2, 4, or 6.
The C6400+ devices contain 8 memory banks; constant can be 0, 2, 4, or 6.
The C6600 devices contain 8 memory banks; constant can be 0, 2, 4, or 6.
The C6700 devices contain 8 memory banks; constant can be 0, 2, 4, or 6.
The C6740 devices contain 8 memory banks; constant can be 0, 2, 4, or 6.
The syntax of the pragma in C is:
#pragma DATA_MEM_BANK ( symbol , constant );
The syntax of the pragma in C++ is:
#pragma DATA_MEM_BANK ( constant );
Both global and local variables can be aligned with the DATA_MEM_BANK pragma. The
DATA_MEM_BANK pragma must reside inside the function that contains the local variable being aligned.
The symbol can also be used as a parameter in the DATA_SECTION pragma.
When optimization is enabled, the tools may or may not use the stack to store the values of local variables.
The DATA_MEM_BANK pragma allows you to align data on any data memory bank that can hold data of the type size of the symbol. This is useful if you need to align data in a particular way to avoid memory bank conflicts in your hand-coded assembly code versus padding with zeros and having to account for the padding in your code.
This pragma increases the amount of space used in data memory by a small amount as padding is used to align data onto the correct bank.
For C6200, the code in
guarantees that array x begins at an address ending in 4 or c (in hexadecimal), and that array y begins at an address ending in 4 or c. The alignment for array y affects its stack placement. Array z is placed in the .z_sect section, and begins at an address ending in 0 or 8.
Example 6-7. Using the DATA_MEM_BANK Pragma
#pragma DATA_MEM_BANK (x, 2); short x[100];
#pragma DATA_MEM_BANK (z, 0);
#pragma DATA_SECTION (z, ".z_sect"); short z[100]; void main()
{
#pragma DATA_MEM_BANK (y, 2); short y[100];
...
}
160 TMS320C6000C/C++ Language Implementation
Copyright © 2012, Texas Instruments Incorporated
SPRU187U – July 2012
Submit Documentation Feedback
www.ti.com
Pragma Directives
6.9.6 The DATA_SECTION Pragma
The DATA_SECTION pragma allocates space for the symbol in C, or the next symbol declared in C++, in a section named section name.
The syntax of the pragma in C is:
#pragma DATA_SECTION ( symbol , " section name ");
The syntax of the pragma in C++ is:
#pragma DATA_SECTION (" section name ");
The DATA_SECTION pragma is useful if you have data objects that you want to link into an area separate from the .bss section. If you allocate a global variable using a DATA_SECTION pragma and you want to reference the variable in C code, you must declare the variable as extern far.
through
demonstrate the use of the DATA_SECTION pragma.
Example 6-8. Using the DATA_SECTION Pragma C Source File
#pragma DATA_SECTION(bufferB, "my_sect") char bufferA[512]; char bufferB[512];
Example 6-9. Using the DATA_SECTION Pragma C++ Source File char bufferA[512];
#pragma DATA_SECTION("my_sect") char bufferB[512];
Example 6-10. Using the DATA_SECTION Pragma Assembly Source File
.global _bufferA
.bss
_bufferA,512,4
.global _bufferB
SPRU187U – July 2012
Submit Documentation Feedback
TMS320C6000C/C++ Language Implementation
Copyright © 2012, Texas Instruments Incorporated
161
Pragma Directives
6.9.7 The Diagnostic Message Pragmas
The following pragmas can be used to control diagnostic messages in the same ways as the corresponding command line options:
Pragma
DIAG_SUPPRESS num
DIAG_REMARK num
DIAG_WARNING num
DIAG_ERROR num
DIAG_DEFAULT num
Option
-pds=num[, num
2
, num
3
...]
-pdsr=num[, num
2
, num
3
...]
-pdsw=num[, num
2
, num
3
...]
-pdse=num[, num
2
, num
3
...] n/a
Description
Suppress diagnostic num
Treat diagnostic num as a remark
Treat diagnostic num as a warning
Treat diagnostic num as an error
Use default severity of the diagnostic www.ti.com
The syntax of the pragmas in C is:
#pragma DIAG_XXX [=]num[, num
2
, num
3
...]
The diagnostic affected (num) is specified using either an error number or an error tag name. The equal sign (=) is optional. Any diagnostic can be overridden to be an error, but only diagnostics with a severity of discretionary error or below can have their severity reduced to a warning or below, or be suppressed. The diag_default pragma is used to return the severity of a diagnostic to the one that was in effect before any pragmas were issued (i.e., the normal severity of the message as modified by any command-line options).
The diagnostic identifier number is output along with the message when the -pden command line option is specified.
6.9.8 The FUNC_ALWAYS_INLINE Pragma
The FUNC_ALWAYS_INLINE pragma instructs the compiler to always inline the named function. The compiler only inlines the function if it is legal to inline the function and the compiler is invoked with any level of optimization (--opt_level=0).
The pragma must appear before any declaration or reference to the function that you want to inline. In C, the argument func is the name of the function that will be inlined. In C++, the pragma applies to the next function declared.
The syntax of the pragma in C is:
#pragma FUNC_ALWAYS_INLINE ( func );
The syntax of the pragma in C++ is:
#pragma FUNC_ALWAYS_INLINE;
Use Caution with the FUNC_ALWAYS_INLINE Pragma
NOTE: The FUNC_ALWAYS_INLINE pragma overrides the compiler's inlining decisions. Overuse of the pragma could result in increased compilation times or memory usage, potentially enough to consume all available memory and result in compilation tool failures.
162 TMS320C6000C/C++ Language Implementation
Copyright © 2012, Texas Instruments Incorporated
SPRU187U – July 2012
Submit Documentation Feedback
www.ti.com
Pragma Directives
6.9.9 The FUNC_CANNOT_INLINE Pragma
The FUNC_CANNOT_INLINE pragma instructs the compiler that the named function cannot be expanded inline. Any function named with this pragma overrides any inlining you designate in any other way, such as using the inline keyword. Automatic inlining is also overridden with this pragma; see
The pragma must appear before any declaration or reference to the function that you want to keep. In C, the argument func is the name of the function that cannot be inlined. In C++, the pragma applies to the next function declared.
The syntax of the pragma in C is:
#pragma FUNC_CANNOT_INLINE ( func );
The syntax of the pragma in C++ is:
#pragma FUNC_CANNOT_INLINE;
6.9.10 The FUNC_EXT_CALLED Pragma
When you use the --program_level_compile option, the compiler uses program-level optimization. When you use this type of optimization, the compiler removes any function that is not called, directly or indirectly, by main. You might have C/C++ functions that are called by hand-coded assembly instead of main.
The FUNC_EXT_CALLED pragma specifies to the optimizer to keep these C functions or any other functions that these C/C++ functions call. These functions act as entry points into C/C++.
The pragma must appear before any declaration or reference to the function that you want to keep. In C, the argument func is the name of the function that you do not want removed. In C++, the pragma applies to the next function declared.
The syntax of the pragma in C is:
#pragma FUNC_EXT_CALLED ( func );
The syntax of the pragma in C++ is:
#pragma FUNC_EXT_CALLED;
Except for _c_int00, which is the name reserved for the system reset interrupt for C/C++programs, the name of the interrupt (the func argument) does not need to conform to a naming convention.
When you use program-level optimization, you may need to use the FUNC_EXT_CALLED pragma with certain options. See
SPRU187U – July 2012
Submit Documentation Feedback
TMS320C6000C/C++ Language Implementation
Copyright © 2012, Texas Instruments Incorporated
163
Pragma Directives www.ti.com
6.9.11 The FUNC_INTERRUPT_THRESHOLD Pragma
The compiler allows interrupts to be disabled around software pipelined loops for threshold cycles within the function. This implements the --interrupt_threshold option for a single function (see
FUNC_INTERRUPT_THRESHOLD pragma always overrides the --interrupt_threshold=n command line option. A threshold value less than 0 assumes that the function is never interrupted, which is equivalent to an interrupt threshold of infinity.
The syntax of the pragma in C is:
#pragma FUNC_INTERRUPT_THRESHOLD ( func , threshold );
The syntax of the pragma in C++ is:
#pragma FUNC_INTERRUPT_THRESHOLD ( threshold );
The following examples demonstrate the use of different thresholds:
• The function foo( ) must be interruptible at least every 2,000 cycles:
#pragma FUNC_INTERRUPT_THRESHOLD (foo, 2000)
• The function foo( ) must always be interruptible.
#pragma FUNC_INTERRUPT_THRESHOLD (foo, 1)
• The function foo( ) is never interrupted.
#pragma FUNC_INTERRUPT_THRESHOLD (foo, -1)
6.9.12 The FUNC_IS_PURE Pragma
The FUNC_IS_PURE pragma specifies to the compiler that the named function has no side effects. This allows the compiler to do the following:
• Delete the call to the function if the function's value is not needed
• Delete duplicate functions
The pragma must appear before any declaration or reference to the function. In C, the argument func is the name of a function. In C++, the pragma applies to the next function declared.
The syntax of the pragma in C is:
#pragma FUNC_IS_PURE ( func );
The syntax of the pragma in C++ is:
#pragma FUNC_IS_PURE;
164 TMS320C6000C/C++ Language Implementation
Copyright © 2012, Texas Instruments Incorporated
SPRU187U – July 2012
Submit Documentation Feedback
www.ti.com
Pragma Directives
6.9.13 The FUNC_IS_SYSTEM Pragma
The FUNC_IS_SYSTEM pragma specifies to the compiler that the named function has the behavior defined by the ANSI/ISO standard for a function with that name.
The pragma must appear before any declaration or reference to the function that you want to keep. In C, the argument func is the name of the function to treat as an ANSI/ISO standard function. In C++, the pragma applies to the next function declared.
The syntax of the pragma in C is:
#pragma FUNC_IS_SYSTEM ( func );
The syntax of the pragma in C++ is:
#pragma FUNC_IS_SYSTEM;
6.9.14 The FUNC_NEVER_RETURNS Pragma
The FUNC_NEVER_RETURNS pragma specifies to the compiler that the function never returns to its caller.
The pragma must appear before any declaration or reference to the function that you want to keep. In C, the argument func is the name of the function that does not return. In C++, the pragma applies to the next function declared.
The syntax of the pragma in C is:
#pragma FUNC_NEVER_RETURNS ( func );
The syntax of the pragma in C++ is:
#pragma FUNC_NEVER_RETURNS;
6.9.15 The FUNC_NO_GLOBAL_ASG Pragma
The FUNC_NO_GLOBAL_ASG pragma specifies to the compiler that the function makes no assignments to named global variables and contains no asm statements.
The pragma must appear before any declaration or reference to the function that you want to keep. In C, the argument func is the name of the function that makes no assignments. In C++, the pragma applies to the next function declared.
The syntax of the pragma in C is:
#pragma FUNC_NO_GLOBAL_ASG ( func );
The syntax of the pragma in C++ is:
#pragma FUNC_NO_GLOBAL_ASG;
SPRU187U – July 2012
Submit Documentation Feedback
TMS320C6000C/C++ Language Implementation
Copyright © 2012, Texas Instruments Incorporated
165
Pragma Directives www.ti.com
6.9.16 The FUNC_NO_IND_ASG Pragma
The FUNC_NO_IND_ASG pragma specifies to the compiler that the function makes no assignments through pointers and contains no asm statements.
The pragma must appear before any declaration or reference to the function that you want to keep. In C, the argument func is the name of the function that makes no assignments. In C++, the pragma applies to the next function declared.
The syntax of the pragma in C is:
#pragma FUNC_NO_IND_ASG ( func );
The syntax of the pragma in C++ is:
#pragma FUNC_NO_IND_ASG;
6.9.17 The FUNCTION_OPTIONS Pragma
The FUNCTION_OPTIONS pragma allows you to compile a specific function in a C or C++ file with additional command-line compiler options. The affected function will be compiled as if the specified list of options appeared on the command line after all other compiler options. In C, the pragma is applied to the function specified. In C++, the pragma is applied to the next function.
The syntax of the pragma in C is:
#pragma FUNCTION_OPTIONS ( func, "additional options" );
The syntax of the pragma in C++ is:
#pragma FUNCTION_OPTIONS( "additional options" );
6.9.18 The INTERRUPT Pragma
The INTERRUPT pragma enables you to handle interrupts directly with C code. In C, the argument func is the name of a function. In C++, the pragma applies to the next function declared.
The syntax of the pragma in C is:
#pragma INTERRUPT ( func );
The syntax of the pragma in C++ is:
#pragma INTERRUPT ;
The code for the function will return via the IRP (interrupt return pointer).
Except for _c_int00, which is the name reserved for the system reset interrupt for C programs, the name of the interrupt (the func argument) does not need to conform to a naming convention.
HWI Objects and the INTERRUPT Pragma
NOTE: The INTERRUPT pragma must not be used when BIOS HWI objects are used in conjunction with C functions. The HWI_enter/HWI_exit macros and the HWI dispatcher contain this functionality, and the use of the C modifier can cause negative results.
166 TMS320C6000C/C++ Language Implementation
Copyright © 2012, Texas Instruments Incorporated
SPRU187U – July 2012
Submit Documentation Feedback
www.ti.com
Pragma Directives
6.9.19 The LOCATION Pragma
The compiler supports the ability to specify the run-time address of a variable at the source level. This can be accomplished with the LOCATION pragma or attribute. Location support is only available in EABI.
The syntax of the pragma in C is:
#pragma LOCATION( x , address );
int x;
The syntax of the pragmas in C++ is:
#pragma LOCATION(address );
int x;
The syntax of the pragma for IAR is:
#pragma location=address
int x;
The syntax of the GCC attribute is:
int x __attribute__((location(address )));
The noinit pragma may be used in conjunction with the location pragma to map variables to special memory locations; see
.
6.9.20 The MUST_ITERATE Pragma
The MUST_ITERATE pragma specifies to the compiler certain properties of a loop. You guarantee that these properties are always true. Through the use of the MUST_ITERATE pragma, you can guarantee that a loop executes a specific number of times. Anytime the UNROLL pragma is applied to a loop,
MUST_ITERATE should be applied to the same loop. For loops the MUST_ITERATE pragma's third argument, multiple, is the most important and should always be specified.
Furthermore, the MUST_ITERATE pragma should be applied to any other loops as often as possible. This is because the information provided via the pragma (especially the minimum number of iterations) aids the compiler in choosing the best loops and loop transformations (that is, software pipelining and nested loop transformations). It also helps the compiler reduce code size.
No statements are allowed between the MUST_ITERATE pragma and the for, while, or do-while loop to which it applies. However, other pragmas, such as UNROLL and PROB_ITERATE, can appear between the MUST_ITERATE pragma and the loop.
6.9.20.1 The MUST_ITERATE Pragma Syntax
The syntax of the pragma for C and C++ is:
#pragma MUST_ITERATE ( min, max, multiple );
The arguments min and max are programmer-guaranteed minimum and maximum trip counts. The trip count is the number of times a loop iterates. The trip count of the loop must be evenly divisible by multiple.
All arguments are optional. For example, if the trip count could be 5 or greater, you can specify the argument list as follows:
#pragma MUST_ITERATE(5);
However, if the trip count could be any nonzero multiple of 5, the pragma would look like this:
#pragma MUST_ITERATE(5, , 5); /* Note the blank field for max */
SPRU187U – July 2012
Submit Documentation Feedback
TMS320C6000C/C++ Language Implementation
Copyright © 2012, Texas Instruments Incorporated
167
Pragma Directives www.ti.com
It is sometimes necessary for you to provide min and multiple in order for the compiler to perform unrolling. This is especially the case when the compiler cannot easily determine how many iterations the loop will perform (that is, the loop has a complex exit condition).
When specifying a multiple via the MUST_ITERATE pragma, results of the program are undefined if the trip count is not evenly divisible by multiple. Also, results of the program are undefined if the trip count is less than the minimum or greater than the maximum specified.
If no min is specified, zero is used. If no max is specified, the largest possible number is used. If multiple
MUST_ITERATE pragmas are specified for the same loop, the smallest max and largest min are used.
6.9.20.2 Using MUST_ITERATE to Expand Compiler Knowledge of Loops
Through the use of the MUST_ITERATE pragma, you can guarantee that a loop executes a certain number of times. The example below tells the compiler that the loop is guaranteed to run exactly 10 times:
#pragma MUST_ITERATE(10,10); for(i = 0; i < trip_count; i++) { ...
In this example, the compiler attempts to generate a software pipelined loop even without the pragma.
However, if MUST_ITERATE is not specified for a loop such as this, the compiler generates code to bypass the loop, to account for the possibility of 0 iterations. With the pragma specification, the compiler knows that the loop iterates at least once and can eliminate the loop-bypassing code.
MUST_ITERATE can specify a range for the trip count as well as a factor of the trip count. For example: pragma MUST_ITERATE(8, 48, 8); for(i = 0; i < trip_count; i++) { ...
This example tells the compiler that the loop executes between 8 and 48 times and that the trip_count variable is a multiple of 8 (8, 16, 24, 32, 40, 48). The multiple argument allows the compiler to unroll the loop.
You should also consider using MUST_ITERATE for loops with complicated bounds. In the following example: for(i2 = ipos[2]; i2 < 40; i2 += 5) { ...
The compiler would have to generate a divide function call to determine, at run time, the exact number of iterations performed. The compiler will not do this. In this case, using MUST_ITERATE to specify that the loop always executes eight times allows the compiler to attempt to generate a software pipelined loop:
#pragma MUST_ITERATE(8, 8); for(i2 = ipos[2]; i2 < 40; i2 += 5) { ...
6.9.21 The NMI_INTERRUPT Pragma
The NMI_INTERRUPT pragma enables you to handle non-maskable interrupts directly with C code. In C, the argument func is the name of a function. In C++, the pragma applies to the next function declared.
The syntax of the pragma in C is:
#pragma NMI_INTERRUPT( func );
The syntax of the pragma in C++ is:
#pragma NMI_INTERRUPT;
The code generated for the function will return via the NRP versus the IRP as for a function declared with the interrupt keyword or INTERRUPT pragma.
Except for _c_int00, which is the name reserved for the system reset interrupt for C programs, the name of the interrupt (function) does not need to conform to a naming convention.
168 TMS320C6000C/C++ Language Implementation
Copyright © 2012, Texas Instruments Incorporated
SPRU187U – July 2012
Submit Documentation Feedback
www.ti.com
Pragma Directives
6.9.22 The NOINIT and PERSISTENT Pragmas
When using EABI, global and static variables will be zero-initialized. However, in applications using nonvolatile memory, it may be desirable to have variables that are not initialized. Noinit variables are global or static variables that are not zero-initialized at startup or reset.
The NOINIT pragma may be used in conjunction with the location pragma to map variables to special memory locations, like memory-mapped registers, without generating unwanted writes.
Noinit variables cannot have an initializer. However, statically-initialized variables may be declared
"persistent" to disable startup initialization. Persistent variables are given an initial value when the code is loaded, but are never again initialized. Persistent and noinit variables behave identically with the exception of whether or not they are initialized at load time.
The syntax of the pragmas in C is:
#pragma NOINIT (x );
int x;
#pragma PERSISTENT (x );
int x=10;
The syntax of the pragmas in C++ is:
#pragma NOINIT;
int x;
#pragma PERSISTENT;
int x=10;
The syntax of the GCC attributes is:
int x __attribute__((noinit));
int x =0 __attribute__((persistent));
6.9.23 The NO_HOOKS Pragma
The NO_HOOKS pragma prevents entry and exit hook calls from being generated for a function.
The syntax of the pragma in C is:
#pragma NO_HOOKS ( func );
The syntax of the pragma in C++ is:
#pragma NO_HOOKS;
See
for details on entry and exit hooks.
SPRU187U – July 2012
Submit Documentation Feedback
TMS320C6000C/C++ Language Implementation
Copyright © 2012, Texas Instruments Incorporated
169
Pragma Directives www.ti.com
6.9.24 The PROB_ITERATE Pragma
The PROB_ITERATE pragma specifies to the compiler certain properties of a loop. You assert that these properties are true in the common case. The PROB_ITERATE pragma aids the compiler in choosing the best loops and loop transformations (that is, software pipelining and nested loop transformations).
PROB_ITERATE is useful only when the MUST_ITERATE pragma is not used or the PROB_ITERATE parameters are more constraining than the MUST_ITERATE parameters.
No statements are allowed between the PROB_ITERATE pragma and the for, while, or do-while loop to which it applies. However, other pragmas, such as UNROLL and MUST_ITERATE, may appear between the PROB_ITERATE pragma and the loop.
The syntax of the pragma for C and C++ is:
#pragma PROB_ITERATE( min , max )
Where min and max are the minimum and maximum trip counts of the loop in the common case. The trip count is the number of times a loop iterates. Both arguments are optional.
For example, PROB_ITERATE could be applied to a loop that executes for eight iterations in the majority of cases (but sometimes may execute more or less than eight iterations):
#pragma PROB_ITERATE(8, 8);
If only the minimum expected trip count is known (say it is 5), the pragma would look like this:
#pragma PROB_ITERATE(5);
If only the maximum expected trip count is known (say it is 10), the pragma would look like this:
#pragma PROB_ITERATE(, 10); /* Note the blank field for min */
6.9.25 The RESET_MISRA Pragma
The RESET_MISRA pragma resets the specified MISRA-C:2004 rules to the state they were before any
CHECK_MISRA pragmas (see
) were processed. For instance, if a rule was enabled on the command line but disabled in the source, the RESET_MISRA pragma resets it to enabled. This pragma accepts the same format as the --check_misra option, except for the "none" keyword.
The syntax of the pragma in C is:
#pragma RESET_MISRA (" {all|required|advisory|rulespec} ")
The rulespec parameter is a comma-separated list of specifiers. See
for details.
6.9.26 The RETAIN Pragma
The RETAIN pragma can be applied to a code or data symbol. It causes a .retain directive to be generated into the section that contains the definition of the symbol. The .retain directive indicates to the linker that the section is ineligible for removal during conditional linking. Therefore, regardless whether or not the section is referenced by another section in the application that is being compiled and linked, it will be included in the output file result of the link.
The syntax of the pragma in C/C++ is:
#pragma RETAIN ( symbol )
The CLINK pragma has the opposite effect of the RETAIN pragma. See
for more details.
170 TMS320C6000C/C++ Language Implementation
Copyright © 2012, Texas Instruments Incorporated
SPRU187U – July 2012
Submit Documentation Feedback
www.ti.com
6.9.27 The SET_CODE_SECTION and SET_DATA_SECTION Pragmas
These pragmas can be used to set the section for all declarations below the pragma.
The syntax of the pragmas in C/C++ is:
#pragma SET_CODE_SECTION ("section name")
Pragma Directives
#pragma SET_DATA_SECTION ("section name")
In
x and y are put in the section mydata. To reset the current section to the default used by the compiler, a blank paramater should be passed to the pragma. An easy way to think of the pragma is that it is like applying the CODE_SECTION or DATA_SECTION pragma to all symbols below it.
Example 6-11. Setting Section With SET_DATA_SECTION Pragma
#pragma SET_DATA_SECTION("mydata") int x; int y;
#pragma SET_DATA_SECTION()
The pragmas apply to both declarations and definitions. If applied to a declaration and not the definition, the pragma that is active at the declaration is used to set the section for that symbol. Here is an example:
Example 6-12. Setting a Section With SET_CODE_SECTION Pragma
#pragma SET_CODE_SECTION("func1") extern void func1();
#pragma SET_CODE_SECTION()
...
void func1() { ... }
In
func1 is placed in section func1. If conflicting sections are specified at the declaration and definition, a diagnostic is issued.
The current CODE_SECTION and DATA_SECTION pragmas and GCC attributes can be used to override the SET_CODE_SECTION and SET_DATA_SECTION pragmas. For example:
Example 6-13. Overriding SET_DATA_SECTION Setting
#pragma DATA_SECTION(x, "x_data")
#pragma SET_DATA_SECTION("mydata") int x; int y;
#pragma SET_DATA_SECTION()
In
x is placed in x_data and y is placed in mydata. No diagnostic is issued for this case.
The pragmas work for both C and C++. In C++, the pragmas are ignored for templates and for implictly created objects, such as implicit constructors and virtual function tables.
SPRU187U – July 2012
Submit Documentation Feedback
TMS320C6000C/C++ Language Implementation
Copyright © 2012, Texas Instruments Incorporated
171
Pragma Directives www.ti.com
6.9.28 The STRUCT_ALIGN Pragma
The STRUCT_ALIGN pragma is similar to DATA_ALIGN, but it can be applied to a structure, union type, or typedef and is inherited by any symbol created from that type. The STRUCT_ALIGN pragma is supported only in C.
The syntax of the pragma is:
#pragma STRUCT_ALIGN( type , constant expression )
This pragma guarantees that the alignment of the named type or the base type of the named typedef is at least equal to that of the expression. (The alignment may be greater as required by the compiler.) The alignment must be a power of 2. The type must be a type or a typedef name. If a type, it must be either a structure tag or a union tag. If a typedef, its base type must be either a structure tag or a union tag.
Since ANSI/ISO C declares that a typedef is simply an alias for a type (i.e. a struct) this pragma can be applied to the struct, the typedef of the struct, or any typedef derived from them, and affects all aliases of the base type.
This example aligns any st_tag structure variables on a page boundary: typedef struct st_tag
{ int a; short b;
} st_typedef;
#pragma STRUCT_ALIGN (st_tag, 128);
#pragma STRUCT_ALIGN (st_typedef, 128);
Any use of STRUCT_ALIGN with a basic type (int, short, float) or a variable results in an error.
6.9.29 The UNROLL Pragma
The UNROLL pragma specifies to the compiler how many times a loop should be unrolled. The UNROLL pragma is useful for helping the compiler utilize SIMD instructions on the C6400 family. It is also useful in cases where better utilization of software pipeline resources are needed over a non-unrolled loop.
The optimizer must be invoked (use --opt_level=[1|2|3] or -O1, -O2, or -O3) in order for pragma-specified loop unrolling to take place. The compiler has the option of ignoring this pragma.
No statements are allowed between the UNROLL pragma and the for, while, or do-while loop to which it applies. However, other pragmas, such as MUST_ITERATE and PROB_ITERATE, can appear between the UNROLL pragma and the loop.
The syntax of the pragma for C and C++ is:
#pragma UNROLL( n );
172
If possible, the compiler unrolls the loop so there are n copies of the original loop. The compiler only unrolls if it can determine that unrolling by a factor of n is safe. In order to increase the chances the loop is unrolled, the compiler needs to know certain properties:
• The loop iterates a multiple of n times. This information can be specified to the compiler via the multiple argument in the MUST_ITERATE pragma.
• The smallest possible number of iterations of the loop
• The largest possible number of iterations of the loop
The compiler can sometimes obtain this information itself by analyzing the code. However, sometimes the compiler can be overly conservative in its assumptions and therefore generates more code than is necessary when unrolling. This can also lead to not unrolling at all.
Furthermore, if the mechanism that determines when the loop should exit is complex, the compiler may not be able to determine these properties of the loop. In these cases, you must tell the compiler the properties of the loop by using the MUST_ITERATE pragma.
TMS320C6000C/C++ Language Implementation
Copyright © 2012, Texas Instruments Incorporated
SPRU187U – July 2012
Submit Documentation Feedback
www.ti.com
The _Pragma Operator
Specifying #pragma UNROLL(1); asks that the loop not be unrolled. Automatic loop unrolling also is not performed in this case.
If multiple UNROLL pragmas are specified for the same loop, it is undefined which pragma is used, if any.
6.10 The _Pragma Operator
The C6000 C/C++ compiler supports the C99 preprocessor _Pragma() operator. This preprocessor operator is similar to #pragma directives. However, _Pragma can be used in preprocessing macros
(#defines).
The syntax of the operator is:
_Pragma (" string_literal ");
The argument string_literal is interpreted in the same way the tokens following a #pragma directive are processed. The string_literal must be enclosed in quotes. A quotation mark that is part of the string_literal must be preceded by a backward slash.
You can use the _Pragma operator to express #pragma directives in macros. For example, the
DATA_SECTION syntax:
#pragma DATA_SECTION( func ," section ");
Is represented by the _Pragma() operator syntax:
_Pragma ("DATA_SECTION( func ,\" section \")")
The following code illustrates using _Pragma to specify the DATA_SECTION pragma in a macro:
...
#define EMIT_PRAGMA(x) _Pragma(#x)
#define COLLECT_DATA(var) EMIT_PRAGMA(DATA_SECTION(var,"mysection"))
COLLECT_DATA(x) int x;
...
The EMIT_PRAGMA macro is needed to properly expand the quotes that are required to surround the section argument to the DATA_SECTION pragma.
SPRU187U – July 2012
Submit Documentation Feedback
TMS320C6000C/C++ Language Implementation
Copyright © 2012, Texas Instruments Incorporated
173
Application Binary Interface www.ti.com
6.11 Application Binary Interface
Selecting one of the two ABIs supported by the C6000 compiler is discussed in
.
An ABI should define how functions that are written separately, and compiled or assembled separately can work together. This involves standardizing the data type representation, register conventions, and function structure and calling conventions. It should define linkname generation from C symbol names. It should define the object file format and the debug format. It should document how the system is initialized.
In the case of C++ it defines C++ name mangling and exception handling support.
An application must be only one of COFF ABI and EABI; these ABIs are not compatible.
6.11.1 COFF ABI
COFF ABI is the only ABI supported by older compilers. To generate object files compatible with older
COFF ABI object files, you must use COFF ABI (--abi=coffabi, the default). This option must also be used when assembly hand-coded assembly source files intended to be used in a COFF ABI application.
6.11.2 EABI
EABI requires the ELF object file format which enables supporting modern language features like early template instantiation and export inline functions support.
TI-specific information on EABI mode is described in
.
To generate object files compatible with EABI, you must use C6000 compiler version 7.2 or greater; see
. The __TI_EABI__ predefined symbol is defined and set to 1 if compiling for EABI and is not
defined otherwise.
6.12 Object File Symbol Naming Conventions (Linknames)
Each externally visible identifier is assigned a unique symbol name to be used in the object file, a socalled linkname. This name is assigned by the compiler according to an algorithm which depends on the name, type, and source language of the symbol. This algorithm may add a prefix to the identifier (typically an underscore), and it may mangle the name. This algorithm may mangle the name.
In COFF ABI, the linkname for all objects and functions is the same as the name in the C source with an added underscore prefix. This prevents any C identifier from colliding with any identifier in the assembly code namespace, such as an assembler keyword.
In EABI, no prefix is used. If a C identifier would collide with an assembler keyword, the compiler will escape the identifier with double parallel bars, which instructs the assembler not to treat the identifier as a keyword. You are responsible for making sure that C identifiers do not collide with user-defined assembly code identifiers.
Name mangling encodes the types of the parameters of a function in the linkname for a function. Name mangling only occurs for C++ functions which are not declared 'extern "C"'. Mangling allows function overloading, operator overloading, and type-safe linking. Be aware that the return value of the function is not encoded in the mangled name, as C++ functions cannot be overloaded based on the return value.
For COFF ABI, the mangling algorithm used closely follows that described in The Annotated Reference
Manual (ARM).
For example, the general form of a C++ linkname for a function named func is:
_func__F parmcodes
Where parmcodes is a sequence of letters that encodes the parameter types of func.
For this simple C++ source file: int foo(int i){ } //global C++ function
This is the resulting assembly code:
_foo__Fi
174 TMS320C6000C/C++ Language Implementation
Copyright © 2012, Texas Instruments Incorporated
SPRU187U – July 2012
Submit Documentation Feedback
www.ti.com
Initializing Static and Global Variables in COFF ABI Mode
The linkname of foo is _foo__Fi, indicating that foo is a function that takes a single argument of type int.
To aid inspection and debugging, a name demangling utility is provided that demangles names into those found in the original C++ source. See
for more information.
For EABI, the mangling algorithm follows that described in the Itanium C++ ABI
( http://www.codesourcery.com/cxx-abi/abi.html
).
int foo(int i) { } would be mangled "_Z3fooi"
6.13 Initializing Static and Global Variables in COFF ABI Mode
The ANSI/ISO C standard specifies that global (extern) and static variables without explicit initializations must be initialized to 0 before the program begins running. This task is typically done when the program is loaded. Because the loading process is heavily dependent on the specific environment of the target application system, in COFF ABI mode the compiler itself makes no provision for initializing to 0 otherwise uninitialized static storage class variables at run time. It is up to your application to fulfill this requirement.
Initialize Global Objects
NOTE: You should explicitly initialize all global objects which you expected the compiler would set to zero by default.
In C6000 EABI mode the uninitialized variables are zero initialized automatically.
6.13.1 Initializing Static and Global Variables With the Linker
If your loader does not preinitialize variables, you can use the linker to preinitialize the variables to 0 in the object file. For example, in the linker command file, use a fill value of 0 in the .bss section:
SECTIONS
{
...
.bss: {} = 0x00;
...
}
Because the linker writes a complete load image of the zeroed .bss section into the output COFF file, this method can have the unwanted effect of significantly increasing the size of the output file (but not the program).
If you burn your application into ROM, you should explicitly initialize variables that require initialization.
The preceding method initializes .bss to 0 only at load time, not at system reset or power up. To make these variables 0 at run time, explicitly define them in your code.
For more information about linker command files and the SECTIONS directive, see the linker description information in the TMS320C6000 Assembly Language Tools User's Guide.
6.13.2 Initializing Static and Global Variables With the const Type Qualifier
Static and global variables of type const without explicit initializations are similar to other static and global variables because they might not be preinitialized to 0 (for the same reasons discussed in
).
For example: const int zero; /* may not be initialized to 0 */
However, the initialization of const global and static variables is different because these variables are declared and initialized in a section called .const. For example: const int zero = 0 /* guaranteed to be 0 */
This corresponds to an entry in the .const section:
.sect
.const
_zero
.word
0
SPRU187U – July 2012
Submit Documentation Feedback
TMS320C6000C/C++ Language Implementation
Copyright © 2012, Texas Instruments Incorporated
175
Changing the ANSI/ISO C Language Mode www.ti.com
This feature is particularly useful for declaring a large table of constants, because neither time nor space is wasted at system startup to initialize the table. Additionally, the linker can be used to place the .const
section in ROM.
You can use the DATA_SECTION pragma to put the variable in a section other than .const. For example, the following C code:
#pragma DATA_SECTION (var, ".mysect"); const int zero=0; is compiled into this assembly code:
.sect
.mysect
_zero
.word
0
6.14 Changing the ANSI/ISO C Language Mode
The --kr_compatible, --relaxed_ansi, and --strict_ansi options let you specify how the C/C++ compiler interprets your source code. You can compile your source code in the following modes:
• Normal ANSI/ISO mode
• K&R C mode
• Relaxed ANSI/ISO mode
• Strict ANSI/ISO mode
The default is normal ANSI/ISO mode. Under normal ANSI/ISO mode, most ANSI/ISO violations are emitted as errors. Strict ANSI/ISO violations (those idioms and allowances commonly accepted by C/C++ compilers, although violations with a strict interpretation of ANSI/ISO), however, are emitted as warnings.
Language extensions, even those that conflict with ANSI/ISO C, are enabled.
K&R C mode does not apply to C++ code.
6.14.1 Compatibility With K&R C (--kr_compatible Option)
The ANSI/ISO C/C++ language is a superset of the de facto C standard defined in Kernighan and
Ritchie's The C Programming Language. Most programs written for other non-ANSI/ISO compilers correctly compile and run without modification.
There are subtle changes, however, in the language that can affect existing code. Appendix C in The C
Programming Language (second edition, referred to in this manual as K&R) summarizes the differences between ANSI/ISO C and the first edition's C standard (the first edition is referred to in this manual as
K&R C).
To simplify the process of compiling existing C programs with the ANSI/ISO C/C++ compiler, the compiler has a K&R option (--kr_compatible) that modifies some semantic rules of the language for compatibility with older code. In general, the --kr_compatible option relaxes requirements that are stricter for ANSI/ISO
C than for K&R C. The --kr_compatible option does not disable any new features of the language such as function prototypes, enumerations, initializations, or preprocessor constructs. Instead, --kr_compatible simply liberalizes the ANSI/ISO rules without revoking any of the features.
The specific differences between the ANSI/ISO version of C and the K&R version of C are as follows:
• The integral promotion rules have changed regarding promoting an unsigned type to a wider signed type. Under K&R C, the result type was an unsigned version of the wider type; under ANSI/ISO, the result type is a signed version of the wider type. This affects operations that perform differently when applied to signed or unsigned operands; namely, comparisons, division (and mod), and right shift: unsigned short u; int i; if (u < i) /* SIGNED comparison, unless --kr_compatible used */
• ANSI/ISO prohibits combining two pointers to different types in an operation. In most K&R compilers, this situation produces only a warning. Such cases are still diagnosed when --kr_compatible is used, but with less severity: int *p; char *q = p; /* error without --kr_compatible, warning with --kr_compatible */
176 TMS320C6000C/C++ Language Implementation
Copyright © 2012, Texas Instruments Incorporated
SPRU187U – July 2012
Submit Documentation Feedback
www.ti.com
Changing the ANSI/ISO C Language Mode
• External declarations with no type or storage class (only an identifier) are illegal in ANSI/ISO but legal in K&R: a; /* illegal unless --kr_compatible used */
• ANSI/ISO interprets file scope definitions that have no initializers as tentative definitions. In a single module, multiple definitions of this form are fused together into a single definition. Under K&R, each definition is treated as a separate definition, resulting in multiple definitions of the same object and usually an error. For example: int a; int a; /* illegal if --kr_compatible used, OK if not */
Under ANSI/ISO, the result of these two definitions is a single definition for the object a. For most K&R compilers, this sequence is illegal, because int a is defined twice.
• ANSI/ISO prohibits, but K&R allows objects with external linkage to be redeclared as static: extern int a; static int a; /* illegal unless --kr_compatible used */
• Unrecognized escape sequences in string and character constants are explicitly illegal under ANSI/ISO but ignored under K&R: char c = '\q'; /* same as 'q' if --kr_compatible used, error if not */
• ANSI/ISO specifies that bit fields must be of type int or unsigned. With --kr_compatible, bit fields can be legally defined with any integral type. For example: struct s
{ short f : 2;
};
/* illegal unless --kr_compatible used */
• K&R syntax allows a trailing comma in enumerator lists: enum { a, b, c, }; /* illegal unless --kr_compatible used */
• K&R syntax allows trailing tokens on preprocessor directives:
#endif NAME /* illegal unless --kr_compatible used */
6.14.2 Enabling Strict ANSI/ISO Mode and Relaxed ANSI/ISO Mode (--strict_ansi and -relaxed_ansi Options)
Use the --strict_ansi option when you want to compile under strict ANSI/ISO mode. In this mode, error messages are provided when non-ANSI/ISO features are used, and language extensions that could invalidate a strictly conforming program are disabled. Examples of such extensions are the inline and asm keywords.
Use the --relaxed_ansi option when you want the compiler to ignore strict ANSI/ISO violations rather than emit a warning (as occurs in normal ANSI/ISO mode) or an error message (as occurs in strict ANSI/ISO mode). In relaxed ANSI/ISO mode, the compiler accepts extensions to the ANSI/ISO C standard, even when they conflict with ANSI/ISO C. The GCC language extensions described in
are available in relaxed ANSI/ISO mode.
SPRU187U – July 2012
Submit Documentation Feedback
TMS320C6000C/C++ Language Implementation
Copyright © 2012, Texas Instruments Incorporated
177
GNU Language Extensions www.ti.com
6.14.3 Enabling Embedded C++ Mode (--embedded_cpp Option)
The compiler supports the compilation of embedded C++. In this mode, some features of C++ are removed that are of less value or too expensive to support in an embedded system. When compiling for embedded C++, the compiler generates diagnostics for the use of omitted features.
Embedded C++ is enabled by compiling with the --embedded_cpp option.
Embedded C++ omits these C++ features:
• Templates
• Exception handling
• Run-time type information
• The new cast syntax
• The keyword mutable
• Multiple inheritance
• Virtual inheritance
Under the standard definition of embedded C++, namespaces and using-declarations are not supported.
The C6000 compiler nevertheless allows these features under embedded C++ because the C++ run-timesupport library makes use of them. Furthermore, these features impose no run-time penalty.
The compiler does not support embedded C++ run-time-support libraries.
6.15 GNU Language Extensions
The GNU compiler collection (GCC) defines a number of language features not found in the ANSI/ISO C and C++ standards. The definition and examples of these extensions (for GCC version 3.4) can be found at the GNU web site, http://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/C-Extensions.html
.
Most of these extensions are also available for C++ source code.
6.15.1 Extensions
Most of the GCC language extensions are available in the TI compiler when compiling in relaxed ANSI mode (--relaxed_ansi) or if the --gcc option is used.
The extensions that the TI compiler supports are listed in
Table 6-4 , which is based on the list of
extensions found at the GNU web site. The shaded rows describe extensions that are not supported.
Extensions
Statement expressions
Local labels
Labels as values
Nested functions
Constructing calls
Naming types (1) typeof operator
Generalized lvalues
Conditionals long long
Hex floats
Complex
Zero length
Variadic macros
Variable length
Table 6-4. GCC Language Extensions
Descriptions
Putting statements and declarations inside expressions (useful for creating smart 'safe' macros)
Labels local to a statement expression
Pointers to labels and computed gotos
As in Algol and Pascal, lexical scoping of functions
Dispatching a call to another function
Giving a name to the type of an expression typeof referring to the type of an expression
Using question mark (?) and comma (,) and casts in lvalues
Omitting the middle operand of a ?: expression
Double long word integers and long long int type
Hexadecimal floating-point constants
Data types for complex numbers
Zero-length arrays
Macros with a variable number of arguments
Arrays whose length is computed at run time
(1)
Feature defined for GCC 3.0; definition and examples at http://gcc.gnu.org/onlinedocs/gcc-3.0.4/gcc/C-Extensions.html
178 TMS320C6000C/C++ Language Implementation SPRU187U – July 2012
Submit Documentation Feedback
Copyright © 2012, Texas Instruments Incorporated
www.ti.com
Extensions
Empty structures
Subscripting
Escaped newlines
Multi-line strings (1)
Pointer arithmetic
Initializers
Compound literals
Designated initializers
Cast to union
Case ranges
Mixed declarations
Function attributes
Attribute syntax
Function prototypes
C++ comments
Dollar signs
Character escapes
Variable attributes
Type attributes
Alignment
Inline
Assembly labels
Extended asm
Constraints
Alternate keywords
Explicit reg vars
Incomplete enum types
Function names
Return address
Other built-ins
Vector extensions
Target built-ins
Pragmas
Unnamed fields
Thread-local
GNU Language Extensions
Table 6-4. GCC Language Extensions (continued)
Descriptions
Structures with no members
Any array can be subscripted, even if it is not an lvalue.
Slightly looser rules for escaped newlines
String literals with embedded newlines
Arithmetic on void pointers and function pointers
Non-constant initializers
Compound literals give structures, unions, or arrays as values
Labeling elements of initializers
Casting to union type from any member of the union
'Case 1 ... 9' and such
Mixing declarations and code
Declaring that functions have no side effects, or that they can never return
Formal syntax for attributes
Prototype declarations and old-style definitions
C++ comments are recognized.
A dollar sign is allowed in identifiers.
The character ESC is represented as \e
Specifying the attributes of variables
Specifying the attributes of types
Inquiring about the alignment of a type or variable
Defining inline functions (as fast as macros)
Specifying the assembler name to use for a C symbol
Assembler instructions with C operands
Constraints for asm operands
Header files can use __const__, __asm__, etc
Defining variables residing in specified registers
Define an enum tag without specifying its possible values
Printable strings which are the name of the current function
Getting the return or frame address of a function (limited support)
Other built-in functions (see
Using vector instructions through built-in functions
Built-in functions specific to particular targets
Pragmas accepted by GCC
Unnamed struct/union fields within structs/unions
Per-thread variables
6.15.2 Function Attributes
The following GCC function attributes are supported: always_inline, const, constructor, deprecated, format, format_arg, malloc, noinline, noreturn, pure, section, unused, used and warn_unused_result.
In addition, the visibility function attribute is supported for EABI mode (--abi=eabi).
The format attribute is applied to the declarations of printf, fprintf, sprintf, snprintf, vprintf, vfprintf, vsprintf, vsnprintf, scanf, fscanf, vfscanf, vscanf, vsscanf, and sscanf in stdio.h. Thus when GCC extensions are enabled, the data arguments of these functions are type checked against the format specifiers in the format string argument and warnings are issued when there is a mismatch. These warnings can be suppressed in the usual ways if they are not desired.
The malloc attribute is applied to the declarations of malloc, calloc, realloc and memalign in stdlib.h.
SPRU187U – July 2012
Submit Documentation Feedback
TMS320C6000C/C++ Language Implementation
Copyright © 2012, Texas Instruments Incorporated
179
GNU Language Extensions www.ti.com
6.15.3 Variable Attributes
The following variable attributes are supported: aligned, deprecated, mode, packed, section, transparent_union, unused, and used.
The used attribute is defined in GCC 4.2 (see http://gcc.gnu.org/onlinedocs/gcc-4.2.4/gcc/Variable-
Attributes.html#Variable-Attributes ).
The packed attribute for structure and union types is available only when there is hardware support for unaligned accesses. For C6000 this means C6400+, C6400, C6740, and C6600.
In addition, the weak variable attribute is supported for EABI mode (--abi=eabi).
6.15.4 Type Attributes
The following type attributes are supported: aligned, deprecated, packed, transparent_union, and unused.
In addition, the visibility type attribute is supported for EABI mode (--abi=eabi).
The packed attribute on struct and union types is available only for target architectures that have hardware support for unaligned access (such as C64x+, C64x).
Members of a packed structure are stored as closely to each other as possible, omitting additional bytes of padding usually added to preserve word-alignment. For example, assuming a word-size of 4 bytes ordinarily has 3 bytes of padding between members c1 and i, and another 3 bytes of trailing padding after member c2, leading to a total size of 12 bytes: struct unpacked_struct { char c1; int i; char c2;};
However, the members of a packed struct are byte-aligned. Thus the following does not have any bytes of padding between or after members and totals 6 bytes: struct __attribute__((__packed__)) packed_struct { char c1; int i; char c2; };
Subsequently, packed structures in an array are packed together without trailing padding between array elements.
Bit fields of a packed structure are bit-aligned. The byte alignment of adjacent struct members that are not bit fields does not change. However, there are no bits of padding between adjacent bit fields.
The packed attribute can only be applied to the original definition of a structure or union type. It cannot be applied with a typedef to a non-packed structure that has already been defined, nor can it be applied to the declaration of a struct or union object. Therefore, any given structure or union type can only be packed or non-packed, and all objects of that type will inherit its packed or non-packed attribute.
The packed attribute is not applied recursively to structure types that are contained within a packed structure. Thus, in the following example the member s retains the same internal layout as in the first example above. There is no padding between c and s, so s falls on an unaligned boundary: struct __attribute__((__packed__)) outer_packed_struct { char c; struct unpacked_struct s; };
It is illegal to implicitly or explicitly cast the address of a packed struct member as a pointer to any nonpacked type except an unsigned char. In the following example, p1, p2, and the call to foo are all illegal.
void foo(int *param); struct packed_struct ps; int *p1 = &ps.i; int *p2 = (int *)&ps.i; foo(&ps.i);
However, it is legal to explicitly cast the address of a packed struct member as a pointer to an unsigned char: unsigned char *pc = (unsigned char *)&ps.i;
The TI compiler also supports an unpacked attribute for an enumeration type to allow you to indicate that the representation is to be an integer type that is no smaller than int; in other words, it is not packed.
180 TMS320C6000C/C++ Language Implementation
Copyright © 2012, Texas Instruments Incorporated
SPRU187U – July 2012
Submit Documentation Feedback
www.ti.com
GNU Language Extensions
6.15.5 Built-In Functions
The following builtin functions are supported: __builtin_abs, __builtin_classify_type, __builtin_constant_p,
__builtin_expect, __builtin_fabs, __builtin_fabsf, __builtin_frame_address, __builtin_labs,
__builtin_memcpy, and __builtin_return_address.
The __builtin_frame_address function returns zero unless the argument is a constant zero.
The __builtin_return_address function always returns zero.
SPRU187U – July 2012
Submit Documentation Feedback
TMS320C6000C/C++ Language Implementation
Copyright © 2012, Texas Instruments Incorporated
181
دانلود
تبلیغات