Ложно-положительный: неопределенное или мусорное значение возвращается вызывающей стороне

Следующий код заполняет результат, используя встроенную сборку:

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 как вывод, как предложено, и по-другому заполнить его в коде ассемблера, но я не могу найти никакой информации о том, как это сделать.

1

Решение

Я подозреваю, что это связано с отсутствием выходное ограничение.

Попробуй это,

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 если ты сделаешь это. По крайней мере, это хорошая проблема для устранения.

2

Другие решения

Я нашел обходной путь, хотя все еще надеюсь на более элегантное решение:

    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;
0

По вопросам рекламы [email protected]