Следующий код заполняет результат, используя встроенную сборку:
uint64_t Foo::f() {
uint64_t result;
asm volatile
("vldmia %1, {q0-q1} \n" // q0-1 = *this
⋮
"vstmia %0, {d0} \n" // result = d0
:: "r"(&result), "r"(this)
: "q0", "q1");
return result;
}
result
переменная безусловно устанавливается в коде сборки, но анализатор XCode, кажется, игнорирует это (анализ потока пропускает прямо от объявления до оператора возврата) и жалуется:
…/BitBoard.cpp:26:9: Undefined or garbage value returned to caller
Есть ли способ успокоить анализатор, не тратя впустую циклов инициализации result
?
РЕДАКТИРОВАТЬ: Я попытался предложить указать ограничение вывода:
: "=r"(&result) : "r"(this), "r"(&result)
Но компилятор выдал «Недопустимое значение lvalue в выводе asm». Удаление &
компилирует, но возвращает, казалось бы, случайные результаты. изменения vstmia %0, {d0}
в vmov %0, d0
также терпит неудачу, с «Недопустимым операндом для инструкции».
Я подозреваю, что я должен отметить result
как вывод, как предложено, и по-другому заполнить его в коде ассемблера, но я не могу найти никакой информации о том, как это сделать.
Я подозреваю, что это связано с отсутствием выходное ограничение.
Попробуй это,
uint64_t Foo::f() {
uint64_t result;
asm /* volatile */
("vldmia %1, {q0-q1} \n" // q0-1 = *this
⋮
"vstmia %0, {d0} \n" // result = d0
: "=w"(result): "r"(this) : "q0", "q1");
return result;
}
Вы должны использовать выход ограничение, "=w"(result)
, чтобы сообщить компилятору, что ассемблер устанавливает значение. Вам, вероятно, не нужно volatile
если ты сделаешь это. По крайней мере, это хорошая проблема для устранения.
Я нашел обходной путь, хотя все еще надеюсь на более элегантное решение:
union {
uint64_t result;
struct { uint32_t a, b; };
};
asm
("vldmia %2, {q0-q1} \n" // q0-1 = *this
⋮
"vmov %0, s0 \n""vmov %1, s1 \n"
: "=r"(a), "=r"(b) : "r"(this)
: "q0", "q1");
return result;