NOTICE: The Processors Wiki will End-of-Life in December of 2020. It is recommended to download any files or other content you may need that are hosted on processors.wiki.ti.com. The site is now set to read only.

Pragmas You Can Understand

From Texas Instruments Wiki
Jump to: navigation, search

Introduction[edit]

This article talks about how to wrap a pragma in a macro for better readability, portability, and maintenance. It is in the form of an extended example. The entire example is shown first. Then it is commented upon a few lines at a time.

Code that uses _Pragma can be built if you use, at a minimum, compilers of the following versions.

Target Version
C6000 v6.0.1
ARM v4.4.0
C5500 v3.3.0
MSP430 v1.0.0
C2000 v5.0.0

The example itself is only tested with the C6000 compiler. It uses pragmas that are only supported by that compiler. The general techniques shown can be applied to any pragma.

Full Example[edit]

<syntaxhighlight lang=c> /* pragma.c */

  1. include <assert.h>
  1. ifdef __TI_COMPILER_VERSION__
  #define PRAGMA(x) _Pragma(#x)
  #define LOOP_COUNT_INFO(min, multiple) \
     PRAGMA(MUST_ITERATE(min,,multiple))
  #define VAR_IN_SECTION(var, section) \
     PRAGMA(DATA_SECTION(var, #section))
  #define PTR_IS_ALIGNED(ptr, pow2) \
     _nassert(((unsigned int) (ptr) & (pow2)-1) == 0);
  1. else
  #define LOOP_COUNT_INFO(min, multiple)
  #define VAR_IN_SECTION(var, section)
  #define PTR_IS_ALIGNED(ptr, pow2)
  1. endif

VAR_IN_SECTION(array, special) int array[100];

int sum(int *p, int length) {

  int i;
  int sum = 0;
  PTR_IS_ALIGNED(p, 8)
  LOOP_COUNT_INFO(8, 4)
  for (i = 0; i < length; i++)
     sum += p[i];
  return sum;

} </syntaxhighlight>

Discussion[edit]

The system header file assert.h

<syntaxhighlight lang="c">

  1. include <assert.h>

</syntaxhighlight>

is included because it defines the _nassert macro referred to by PTR_IS_ALIGNED.

The test against __TI_COMPILER_VERSION__

<syntaxhighlight lang="c">

  1. ifdef __TI_COMPILER_VERSION__

</syntaxhighlight>

is how the macros are defined to proper effect when used under a TI compiler, or defined to do nothing when used under some other compiler. The identifier __TI_COMPILER_VERSION__ is predefined by TI compilers.

These lines

<syntaxhighlight lang="c">

  #define PRAGMA(x) _Pragma(#x)
  #define LOOP_COUNT_INFO(min, multiple) \
     PRAGMA(MUST_ITERATE(min,,multiple))

</syntaxhighlight>

define the LOOP_COUNT_INFO macro, which gives the compiler extra information about how many times a loop may iterate. It wraps usage of the MUST_ITERATE pragma.

Pragmas, as first introduced in the C language, are preprocessing directives which perform some compiler specific action. The general form of pragmas is defined by the C language

<syntaxhighlight lang="c">

  1. pragma token-sequence

</syntaxhighlight>

Any further details are left to each compiler to define. The TI compilers define several pragmas, two of which are used in the example. Consult the Compiler User’s Guide for your target for more information on what specific pragmas are available, and how they work.

One problem with supplying a pragma in the form a preprocessing directive is that it cannot be generated by use of another preprocessing macro. This deficiency gives rise to the special preprocessing operator _Pragma. The operand of _Pragma is a string literal. This

<syntaxhighlight lang="c"> _Pragma(“sequence of tokens”) </syntaxhighlight>

is the same as

<syntaxhighlight lang="c">

  1. pragma sequence of tokens

</syntaxhighlight>

Preprocessing macros can generate the _Pragma operator.

A first attempt at writing a macro to generate a _Pragma might be as follows

<syntaxhighlight lang="c">

  #define LOOP_COUNT_INFO(min, multiple) \
     _Pragma("MUST_ITERATE(min,,multiple)")

</syntaxhighlight>

That doesn’t work. The min and multiple arguments of the LOOP_COUNT_INFO macro are not replaced inside the quotes of the _Pragma operator. You can attempt to use preprocessing to see this. The option –ppc instructs the compiler to process all the preprocessing directives (the lines that begin with #) and place the result in a file with the extension .pp.

C:\some\dir>cl6x -ppc pragma.c

C:\some\dir>more pragma.pp
…
   _nassert(((unsigned int) (p) & (8)-1) == 0);

   for (i = 0; i < length; i++)
...

The LOOP_COUNT_INFO macro is invoked on the line just before the for loop. It is preprocessed into nothing that can be seen here. Such is the case with preprocessing directives, including the _Pragma operator. You can work around this by temporarily changing _Pragma, wherever it appears, to something else like test_Pragma

   #define LOOP_COUNT_INFO(min, multiple) \
      test_Pragma("MUST_ITERATE(min,,multiple)")
…
C:\some\dir>more pragma.pp
…
   _nassert(((unsigned int) (p) & (8)-1) == 0);
   test_Pragma("MUST_ITERATE(min,,multiple)")
   for (i = 0; i < length; i++)
...

Now you can see that, even though the LOOP_COUNT_INFO macro is invoked with min=8 and multiple=4, those arguments are not replaced inside the quotes of the argument to _Pragma.

This difficulty is overcome by using a helper macro named PRAGMA:

<syntaxhighlight lang="c">

  #define PRAGMA(x) _Pragma(#x)

</syntaxhighlight>

This macro uses the ‘#’ operator to make a string of its argument, and applies the _Pragma operator to it. When it is invoked, its argument x is evaluated before it is changed into a string. Therefore, in this example

<syntaxhighlight lang="c">

  #define LOOP_COUNT_INFO(min, multiple) \
     PRAGMA(MUST_ITERATE(min,,multiple))

</syntaxhighlight>

The arguments min and multiple of the LOOP_COUNT_INFO macro are replaced prior to invocation of the PRAGMA macro. This can be verified using the preprocessing steps described earlier

<syntaxhighlight lang="c">

  test_Pragma("MUST_ITERATE(8,,4)")

</syntaxhighlight>

Don’t forget to change test_Pragma back to _Pragma.

The MUST_ITERATE pragma takes 3 arguments, in this order:

  • min – indicates the loop will iterate at least this many times
  • max – indicates the loop will iterate a maximum of this many times
  • multiple – indicates the loop will always iterate a multiple of this many times

Any of the arguments may be omitted. The maximum is the most often omitted argument. That is why LOOP_COUNT_INFO does not account for it, but writes the MUST_ITERATE arguments as min,,multiple.

The lines

<syntaxhighlight lang="c">

  #define VAR_IN_SECTION(var, section) \
     PRAGMA(DATA_SECTION(var, #section))

</syntaxhighlight>

wrap usage of the DATA_SECTION pragma. This pragma instructs the compiler to place the global data object in the given section instead of the default section .bss. This allows, among other things, more precise placement of the data when linking. Note the use of the ‘#’ operator on the section name argument. This is because the DATA_SECTION pragma itself, whether invoked via #pragma or _Pragma, requires that the section name argument be a quoted string literal.

The lines

<syntaxhighlight lang="c">

  #define PTR_IS_ALIGNED(ptr, pow2) \
     _nassert(((unsigned int) (ptr) & (pow2)-1) == 0);

</syntaxhighlight>

are similar to a pragma in effect, yet do not use a pragma. The intrinsic _nassert is related to the assert macro defined in assert.h. While the assert macro results in code that checks its expression at runtime and issues a message if it is false, the _nassert intrinsic results in no code. The expression to _nassert is presumed by the compiler to always be true. This extra knowledge of the source often leads to improved optimization. In this case, the PTR_IS_ALIGNED macro indicates the pointer expression is always aligned on an address at the given power of 2, which can lead to the use of more efficient data access instructions that require such alignment.

The lines

<syntaxhighlight lang="c">

  1. else
  #define LOOP_COUNT_INFO(min, multiple)
  #define VAR_IN_SECTION(var, section)
  #define PTR_IS_ALIGNED(ptr, pow2)
  1. endif

</syntaxhighlight>

define those macros to do nothing when a non-TI compiler is being used.

The rest of the example shows straightforward use of the macros.

Please make careful note of the use, or non-use, of semicolons throughout the example. A semicolon must not appear between a _Pragma and the statement it affects. That is why the LOOP_COUNT_INFO and VAR_IN_SECTION macros do not end in semicolons when they are defined or invoked. A semicolon must appear at the end of an _nassert statement. Thus a semicolon must be part of either the definition or the invocation of the PTR_IS_ALIGNED macro. The semicolon is written in the definition so that all the macros are consistently invoked without a semicolon.

For more details on _Pragma, perform an Internet search on the term “Pragma operator”.

E2e.jpg {{
  1. switchcategory:MultiCore=
  • For technical support on MultiCore devices, please post your questions in the C6000 MultiCore Forum
  • For questions related to the BIOS MultiCore SDK (MCSDK), please use the BIOS Forum

Please post only comments related to the article Pragmas You Can Understand here.

Keystone=
  • For technical support on MultiCore devices, please post your questions in the C6000 MultiCore Forum
  • For questions related to the BIOS MultiCore SDK (MCSDK), please use the BIOS Forum

Please post only comments related to the article Pragmas You Can Understand here.

C2000=For technical support on the C2000 please post your questions on The C2000 Forum. Please post only comments about the article Pragmas You Can Understand here. DaVinci=For technical support on DaVincoplease post your questions on The DaVinci Forum. Please post only comments about the article Pragmas You Can Understand here. MSP430=For technical support on MSP430 please post your questions on The MSP430 Forum. Please post only comments about the article Pragmas You Can Understand here. OMAP35x=For technical support on OMAP please post your questions on The OMAP Forum. Please post only comments about the article Pragmas You Can Understand here. OMAPL1=For technical support on OMAP please post your questions on The OMAP Forum. Please post only comments about the article Pragmas You Can Understand here. MAVRK=For technical support on MAVRK please post your questions on The MAVRK Toolbox Forum. Please post only comments about the article Pragmas You Can Understand here. For technical support please post your questions at http://e2e.ti.com. Please post only comments about the article Pragmas You Can Understand here.

}}

Hyperlink blue.png Links

Amplifiers & Linear
Audio
Broadband RF/IF & Digital Radio
Clocks & Timers
Data Converters

DLP & MEMS
High-Reliability
Interface
Logic
Power Management

Processors

Switches & Multiplexers
Temperature Sensors & Control ICs
Wireless Connectivity