Предварительно определенные макросы компилятора Blackfin Печать
Добавил(а) microsin   

Компилятор ccblkfn определяет макросы, предоставляющие информацию о компиляторе, исходном файле и указанных опциях командной строки (predefined macros). Эти макросы могут проверяться с помощью директивы #ifdef и других подобных, чтобы управлять процессом компиляции программы. Что-то подобное делается определением макросов в системных заголовочных файлах.

Примечание: кроме предопределенных макросов, также есть предопределенные утверждения (Predefined Assertions), см. врезку ниже.

Опция командной строки -A name (токены) указывает компилятору утвердить (assert) имя в качестве предиката с заданными токенами. Это дает тот же эффект, как директива препроцессора #assert. Заранее определенные утверждения (predefined assertions) перечислены в таблице 1-8.

Таблица 1-8. Predefined Assertions.

Assertion Значение
system embedded
machine adspblkfn
cpu adspblkfn
compiler ccblkfn

Опция -A name (value) эквивалентна включению в компилируемый исходный код директивы:

#assert name(value)

После этого утвержденные имена могут быть проверены препроцессором:

#if #name(value)
   // какие-то действия
   ...
#else 
   // какие-то другие действия
   ...
#endif

Например, утверждения по умолчанию могут быть проверены следующим образом:

#if #machine(adspblkfn)
   // какие-то действия
   ...
#endif

Примечание: когда используется опция -A, для круглых скобок в утверждении нужно применять кавычки, чтобы предотвратить неправильную интерпретацию опции -A. В директиве #assert исходного файла кавычки не нужны.

Макросы, такие как __DATE__, могут быть полезны при встраивании в текстовые строки. Оператор # в теле макроса полезен для преобразования таких символов в текстовые конструкции.

В таблице 1-41 описываются предопределенные макросы, которые создает компилятор ccblkfn. Многие опции зависят от опций командной строки компилятора, см. [2].

Таблица 1-41. Predefined Compiler Macros.

Макрос Функция
_ADI_FX_LIBIO Определен как 1, когда компилируется с опцией -fixed-point-io.
_ADI_COMPILER Определен как 1.
__ADSPBF50x__ Определен как 1, когда целевой процессор (установленный опцией -proc) ADSP-BF504, ADSP-BF504F или ADSP-BF506F.
__ADSPBF51x__ Определен как 1, когда целевой процессор (установленный опцией -proc) ADSP-BF512, ADSP-BF514, ADSP-BF516 или ADSP-BF518.
__ADSPBF52x__ Определен как 1, когда целевой процессор (установленный опцией -proc) ADSP-BF522, ADSP-BF524, ADSP-BF526, ADSP-BF523, ADSP-BF525 или ADSP-BF527.
__ADSPBF52xLP__ Определен как 1, когда целевой процессор (установленный опцией -proc) ADSP-BF522, ADSP-BF524, ADSP-BF526, ADSP-BF523, ADSP-BF525 или ADSP-BF527.
__ADSPBF52xLP__ Определен как 1, когда целевой процессор (установленный опцией -proc) ADSP-BF522, ADSP-BF524 или ADSP-BF526.
__ADSPBF53x__ Определен как 1, когда целевой процессор (установленный опцией -proc) ADSP-BF531, ADSP-BF532, ADSP-BF533, ADSP-BF534, ADSP-BF536, ADSP-BF537, ADSP-BF538 или ADSP-BF539. Примечание: это не включает процессор ADSP-BF535 processor.
__ADSPBF54x__ Определен как 1, когда целевой процессор (установленный опцией -proc) ADSP-BF542, ADSP-BF544, ADSP-BF547, ADSP-BF548 или ADSP-BF549.
__ADSPBF56x__ Определен как 1, когда целевой процессор (установленный опцией -proc) ADSP-BF561.
__ADSPBF59x__ Определен как 1, когда целевой процессор (установленный опцией -proc) ADSP-BF592-A.
__ADSPBLACKFIN__ Всегда определен как 1.
__ADSPLPBLACKFIN__ Определен как 1, когда целевой процессор (установленный опцией -proc) относится к мало потребляющим (low-power core). Это включает процессоры ADSP-BF504, ADSP-BF504F, ADSP-BF506F, ADSP-BF512, ADSP-BF514, ADSP-BF516, ADSP-BF518, ADSP-BF522, ADSP-BF523, ADSP-BF524, ADSP-BF525, ADSP-BF526, ADSP-BF527, ADSP-BF531, ADSP-BF532, ADSP-BF533, ADSP-BF534, ADSP-BF536, ADSP-BF537, ADSP-BF538, ADSP-BF539, ADSP-BF542, ADSP-BF547, ADSP-BF548, ADSP-BF549, ADSP-BF561 или ADSP-BF592-A.
__ADSPBF506F_FAMILY__ Определен как 1, когда целевой процессор (установленный опцией -proc) ADSP-BF504, ADSP-BF504F или ADSP-BF506F.
__ADSPBF518_FAMILY__ Эквивалент __ADSPBF51x__.
__ADSPBF526_FAMILY__ Эквивалент __ADSPBF52xLP__.
__ADSPBF527_FAMILY__ Эквивалент __ADSPBF52x__.
__ADSPBF533_FAMILY__ Эквивалент __ADSPBF53x__.
__ADSPBF535_FAMILY__ Определен как 1, когда целевой процессор (установленный опцией -proc) ADSP-BF535.
__ADSPBF537_FAMILY__ Эквивалент __ADSPBF53x__.
__ADSPBF538_FAMILY__ Эквивалент __ADSPBF53x__.
__ADSPBF548_FAMILY__ Эквивалент __ADSPBF54x__.
__ADSPBF548M_FAMILY__ Определен как 1, когда целевой процессор (установленный опцией -proc) ADSP-BF542M, ADSP-BF544M, ADSP-BF547M, ADSP-BF548M или ADSP-BF549M.
__ADSPBF592_FAMILY__ Определен как 1, когда целевой процессор (установленный опцией -proc) ADSP-BF592-A.
__ANALOG_EXTENSIONS__ Определен как 1. Если разрешена проверка совместимости MISRA, то этот макрос не определен.
__cplusplus Определен как 199711L, когда код компилируется в режиме C++.
__DATE__ Препроцессор разворачивает этот макрос в строковую константу, в которой находится дата. Строка даты имеет формат mm dd yyyy (стандарт ANSI).
__DOUBLES_ARE_FLOATS__ Определен как 1, когда размер типа double такой же, как у типа float обычной точности (single-precision float type). Когда используется опция командной строки компилятора -double-size-64, этот макрос не определен.
__ECC__ Всегда определен как 1.
__EDG__ Всегда определен как 1. Это определение обозначает использование фронт-энда Edison Design Group.
__EDG_VERSION__ Всегда целочисленное значение, представляющее версию компилятора фронт-энда.
__EXCEPTIONS Определен как 1, когда разрешена обработка исключений (exception handling) языка C++ (с использованием опции -eh).
__FILE__ Препроцессор разворачивает этот макрос в строковую константу, содержащую имя текущего входного файла. Эта строка совпадает с именем файла, указанного в командной строке или в команде препроцессора #include (стандарт ANSI).
_INSTRUMENTED_PROFILING Определен как 1, когда разрешен инструментальный профайлинг (с помощью опции -p командной строки компилятора).
_LANGUAGE_C Всегда определен как 1.
__LINE__ Препроцессор разворачивает этот макрос в десятичную целочисленную константу, представляющую номер текущей строки (стандарт ANSI).
_MISRA_RULES Определен как 1, когда компиляция происходит в режиме MISRA-C.
__NO_BUILTIN Определен как 1, когда компиляция происходит с использованием опции -no-builtin командной строки компилятора.
__NUM_CORES__ Определен в количество ядер выбранного целевого процессора. Например, когда компиляция происходит для процессора ADSP-BF533, __NUM_CORES__ определен как 1, а при компиляции для процессора ADSP-BF561 __NUM_CORES__ определен как 2.
__RTTI Определен как 1, когда разрешена информация о типах времени выполнения C++ (run-time type information) с помощью опции командной строки компилятора -rtti.
__SIGNED_CHARS__ Определен как 1 за исключением случаев, когда компиляция происходит с опцией -unsigned-char.
__STDC__ Всегда определен как 1.
__STDC_VERSION__ Определен как 199409L, когда компиляция происходит в режиме C89, и как 199901L, когда компиляция происходит в режиме C99.
__TIME__ Препроцессор разворачивает этот макрос в строковую константу, содержащую текущее время. Формат этой строки hh:mm:ss (стандарт ANSI).
__VERSION__ Определен как строковая константа, содержащая номер версии компилятора, используемого для компиляции этого модуля.
__VERSIONNUM__ Определен как целочисленная константа __VERSION__, сконструированная из номера версии компилятора. Каждый компонент версии использует 8 бит, и самый значащий байт значения представляет самый значимый (первый) компонент номера версии. Например, компилятор версии 7.1.0.0 определит __VERSIONNUM__ как 0x07010000, и версии 7.1.1.10 определит __VERSIONNUM__ как 0x0701010A.
__VISUALDSPVERSION__ Препроцессор определяет этот макрос в шестнадцатеричное число из 8 цифр, обозначающее релиз VisualDSP++, в форме 0xMMmmuurr, где:
   – MM это major номер релиза,
   – mm minor номер релиза,
   – uu номер обновления,
   – rr это "00", зарезервировано для будущего использования.

Например, VisualDSP++ 5.0 Update 1 получит __VISUALDSPVERSION__ как 0x05000100.
__WORKAROUNDS_ENABLED Определен как 1, если компилятором реализован любой способ обхода ошибки кристалла (hardware workaround). Этот макрос установлен, если у опции -si-revision применено значение, отличающееся от "none", или если выбран любой специфичный workaround с помощью опции -workaround.

[Написание макросов препроцессора]

#define имя блок_текста

Макрос это определенное пользователем имя или строка, вместо которой препроцессор подставляет определенный пользователем блок текста. Для создания макроса используется команда препроцессора #define препроцессора. Когда определение макроса имеет аргументы, препроцессор модифицирует создаваемый блок текста, подставляя аргументы макроса.

Составные макросы. Составным макросом (Compound Macro) называют макрос, который состоит из нескольких строк. Продолжение макроса в следующей строке обеспечивается обратным слешем (\) в конце строки. Составной макрос может работать так же, как встроенная (inline) функция.

#define имя строка1  \
            строка2  \
            строка3

Замечание: при любой возможности используйте inline-функции (встраиваемые функции) вместо составных макросов. Если все-таки составной макрос необходим, определяйте составной макрос так, чтобы его можно было использовать наподобие вызовов функции. Это делает исходный код проще для чтения и поддержки.

Ниже в качестве примера определены две версии составного макроса SKIP_SPACES.

Вариант 1:

/* SKIP_SPACES, обычная реализация составного макроса *
/#define SKIP_SPACES(p, limit)  {    \
   char *lim = (limit);             \
      while (p != lim)            { \
         if (*(p)++ != ' ')       { \
            (p)--;                  \
            break;                  \
         }                          \
   }                                \
}

Вариант 2:

/* SKIP_SPACES, "закрытый" макрос *
/#define SKIP_SPACES(p, limit)   \
   do {                         \
      char *lim = (limit);      \
      while ((p) != lim)      { \
         if (*(p)++ != ' ')   { \
            (p)--;              \
            break;              \
         }                      \
      }                         \
   } while (0)

Во втором варианте тело макроса обрамлено однопроходным циклом do {...} while (0), что превращает его в один оператор, когда он обработан препроцессором. Первый вариант, в отличие от второго варианта, препроцессор разворачивает в составной оператор. С макросом, который разворачивается в составной оператор, Вы иногда можете пропустить точку с запятой после вызова макроса, и компилятор ничего не заметит, получится допустимая программа. Это приводит к необходимости помнить, что конкретно используется - функция или макрос, и нужна ли для макроса завершающая точка с запятой, или нет. Конструкция с обрамлением do {...} while (0) лишена такого недостатка, макрос можно считать функцией, и завершать его вызов точкой с запятой.

Например:

/* SKIP_SPACES, закрытый макрос, заканчивается без ';' */
if (*p != 0)
   SKIP_SPACES (p, lim);
else ...

Этот макрос развернется в следующий код:

if (*p != 0)
   do {
      ...
   } while (0);
else ...

Без конструкции do {...} while (0) преобразование макроса было бы таким:

if (*p != 0)
   {
      ...
   };  /* Скорее всего это совсем не то, что нужно было получить... */
else

[Ссылки]

1. VisualDSP++: использование предварительно определенных макросов препроцессора.
2Опции командной строки компилятора Blackfin.