Как включить новую строку в макрос C++ или как использовать шаблоны C++, чтобы сделать то же самое?

Я видел следующий вопрос: Как создать новую строку в макросе cpp?

Позвольте мне дать краткое требование о необходимости новой строки в препроцессоре C++. Я работаю над компилятором ARM Realview 3.1 над кодом, который использует встроенный ассемблерный код с кодом C++.

#define DEFINE_FUNCTION(rtype, op, val) \
    __asm rtype nt_##op(void*) { \   
      str lr, [sp, ##val];bl vThunk_##op;ldr lr, [sp,##val];bx lr; \
    } \
   void vThunk_##op(void*)

DEFINE_FUNCTION(void*, mov_lt, #0x04)
{
     // do some operation
}

Вышеупомянутый макрос объявляет встроенную функцию сборки, которая принудительно требует новой строки между каждым оператором в теле функции.

Я думаю, это потому, что текст в теле функции отправляется вслепую ARM-ассемблеру компилятором ARM.

Почему препроцессор C++ до сих пор не поддерживает многострочные замены? а также я не могу использовать # в строке замены. например, для такого рода сборки,

str lr, [sp, #0x04]

Я перепробовал много методов и способов, но ничего не получилось. Ассемблер / компилятор ARM настолько прост, что в GCC нет API, подобного asm volatile.

Макрос DEFINE_FUNCTION используется во многих местах, поэтому не может его игнорировать.

Итак, в крайнем случае подумайте о следующих решениях:

  • Использование препроцессора m4 вместо препроцессора C++
  • Используйте шаблоны C++, чтобы как-то добиться этого, и замените DEFINE_FUNCTION, используя grep/sed

Может кто-нибудь дать мне указатели или способы сделать вышеупомянутые вещи? Я не могу использовать любой компилятор, кроме компилятора ARM Realview 3.1.

Мне нужно расширение, как показано ниже, с новой строкой для, DEFINE_FUNCTION(void*, mov_lt, #0x04) {},

__asm void* nt_mov_lt(void*) {   
      str lr, [sp, 0x04];
      bl vThunk_mov_lt;
      ldr lr, [sp,0x04];
      bx lr;
    }
 void vThunk_mov_lt(void*)
 {
     // do something
  }

4 ответа

Решение

Я решил вышеупомянутую проблему с помощью препроцессора GNU m4.

m4_define('DEFINE_FUNCTION','
     __asm rtype nt_$2(void*) {  
      str lr, [sp, $3];
      bl vThunk_$1;
      ldr lr, [sp,$3];
      bx lr;
    } 
   void vThunk_$2(void*)')

DEFINE_FUNCTION(void*, mov_lt, 0x04)
{
}

Предварительная обработка приведенного выше кода с использованием m4 решила мою проблему с требованием новой строки в коде. Запустил m4 -P в качестве события предварительной сборки, чтобы исходный файл обрабатывался еще до того, как начался этап препроцессора C и стадии компиляции.

Спасибо за помощь и извиняюсь за то, что много путаю. Но в последних компиляторах C++ действительно есть место для хорошего препроцессора макросов.

Каждая газовая версия имеет свой символ замены новой строки, например, AVR имеет $ look для символа газовой версии ARM

Я не знаю различных компиляторов C и C++ для ARM, но следующее работает в 2022 году как минимум с компиляторами Microsoft для Windows x86/x64, а также с компиляторами Open Watcom (даже для DOS):

      #define MY_MACRO { \
  _asm { \
    _asm MOV AX, 0 \
    _asm MOV BX, 1 \
  } \
}

Препроцессор превращает это в одну строку, удаляя символы продолжения и символы новой строки, но каждый _asmтокен разделяет инструкции, как если бы была новая строка.

Чтобы еще раз подчеркнуть, я понятия не имею об ARM, и синтаксис для GCC x86/x64 все равно отличается, но, возможно, вы сможете применить эту идею к своей проблеме.

PS Я знаю, что крайние фигурные скобки лишние, но я предпочитаю именно их при написании макросов.

Ваш пример очень запутанный, но разве это не сработает?

#define DEFINE_FUNCTION(rtype, op, val) \
    __asm rtype nt_##op(void*) { \   
      str lr, [sp, val];\
      bl vThunk_##op;\
      ldr lr, [sp,val];\
      bx lr;\
    }\
   void vThunk_##op(void*)

и когда называется как

DEFINE_FUNCTION(void*, mov_lt, 0x04)  // notice no # here
{
     // do some operation
}

вы получите

__asm void* nt_mov_lt(void*) {   
      str lr, [sp, 0x04];
      bl vThunk_mov_lt;
      ldr lr, [sp,0x04];
      bx lr;
    }
 void vThunk_mov_lt(void*)
 {
     // do something
 }

это именно то, что вы просите.

Другие вопросы по тегам