Как стать автором
Обновить

Комментарии 5

С Int_VecDo3 разве не ошибка в анализаторе? Смотрите, GetNumVectorElements возвращает числа из множества {0, 1, 2, 3, 4}. Если n >= 1 , то проблемы с n + n - 2 нет. Значит, беда будет в случае n == 0.
Это бывает, если аргумент GetNumVectorElements, полученный в строке VectorSize sz = GetVecSize(op);, не лежит во множестве {V_Single, V_Pair, V_Triple, V_Quad} == {1, 2, 3, 4}. Хорошо, а что же такое GetVecSize?

static inline VectorSize GetVecSize(MIPSOpcode op) {
	int a = (op >> 7) & 1;
	int b = (op >> 14) & 2;
	return (VectorSize)(a + b + 1);  // Safe, there are no other possibilities
}

MIPSOpcode - просто обёртка над uint32_t. Как видим, здесь вычисляются a и b. Первое - либо 0, либо 1. Второе - либо 0, либо 2. Поэтому их сумма принадлежит множеству {0, 1, 2, 3}. Докидывая в сумму единичку, получаем {1, 2, 3, 4}, т.е. sz всегда корректно, а значит, n тоже.

Спасибо за интересное замечание!

Мне понятна ваша логика. Однако, если следовать ей, то можно сделать вывод, что дефолтная ветвь в GetNumVectorElements является недостижимым кодом:

static inline int GetNumVectorElements(VectorSize sz) { switch (sz) { case V_Single: return 1; case V_Pair: return 2; case V_Triple: return 3; case V_Quad: return 4; default: return 0; //unreachable code } }

Недостижимый код тоже является ошибкой и в данном случае можно сказать, что является меньшим злом. Итак, имеем недостижимый код в виде default: return 0;

Можно убрать эту ветвь, но тогда получим предупреждение от компилятора, что control flow graph функции имеет путь без возвращаемого значения. Хорошо, заменим возвращаемое значение на std::optional и на этом казалось бы всё.

Но! Можно всё же заметить, что VectorSize имеет такой вариант значения как V_Invalid = -1, который как раз обрабатывается этой ветвью и может прийти из указанной вами функции GetVecSize.

Предположим даже, что обёртка MIPSOpcode , которая представляет из себя Memory::Opcode всегда будет иметь значения из того же диапазона, что и uint32_t, а переменные a и b , которые удачно объявлены как int, никогда не будут отрицательными. И результат каста (VectorSize)(a + b + 1) тоже никогда не будет V_Invalid (-1).

Есть ли гарантия, что в результате рефакторинга или других изменений в коде всё это не рассыплется как карточный домик?

Предположим даже, что обёртка MIPSOpcode , которая представляет из себя Memory::Opcode всегда будет иметь значения из того же диапазона, что и uint32_t, а переменные a и b , которые удачно объявлены как int, никогда не будут отрицательными.

Сейчас вообще не понял)

Ну, Memory::Opcode олицетворяет 4 байта, в которых закодирована команда процессору (RISC, всё такое, удобно), конечно, он будет принимать значения, как и то, что у него под капотом - uint32_t. А как объявлены переменные a и b, неважно, т.к. мы срезаем битовыми масками по степени двойки в каждом случае.

Что же касается рефакторинга... Ну, у нас есть тесты. Их мы гоняем на каждый PR, чтобы сравнить, не перестали ли мы походить на реальную PSP. Да-да-да, покрытия идеального не бывает, избыточность тестирования... Это всё ясно, но лучше варианта нет. Те же статические анализаторы могут ошибаться, как мы видим.

Что касается dummyThreadHackAddr, я его просто ещё не отрефакторил. Месяц назад я вытащил код, относящийся к системе AdhocMatching, в отдельные файлы, а потом почистил hadouken codestyle. На очереди AdhocCtl как раз, просто руки не дошли.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий