SWDEV-424956 - Fix half vector printf issue
Refactor PrintfDbg::outputArgument() to remove potential risk. Fix half vector printf issue on all devices. Fix FEAT-56794 as well. Change-Id: Iae39359d2128588def2e43d77fe58e868b8e71ff
이 커밋은 다음에 포함됨:
+16
-15
@@ -246,7 +246,7 @@ static constexpr size_t ConstStr = 0xffffffff;
|
||||
static constexpr char Separator[] = ",\0";
|
||||
|
||||
size_t PrintfDbg::outputArgument(const std::string& fmt, bool printFloat, size_t size,
|
||||
const uint32_t* argument) const {
|
||||
const void* argument) const {
|
||||
// Serialize the output to the screen
|
||||
amd::ScopedLock k(dev().lockAsyncOps());
|
||||
|
||||
@@ -256,7 +256,7 @@ size_t PrintfDbg::outputArgument(const std::string& fmt, bool printFloat, size_t
|
||||
// copiedBytes should be as number of printed chars
|
||||
copiedBytes = 0;
|
||||
//(null) should be printed
|
||||
if (*argument == 0) {
|
||||
if (*(reinterpret_cast<const unsigned char*>(argument)) == 0) {
|
||||
amd::Os::printf(fmt.data(), 0);
|
||||
// copiedBytes = strlen("(null)")
|
||||
copiedBytes = 6;
|
||||
@@ -291,11 +291,9 @@ size_t PrintfDbg::outputArgument(const std::string& fmt, bool printFloat, size_t
|
||||
case 2:
|
||||
case 4:
|
||||
if (printFloat) {
|
||||
uint32_t arg = *argument;
|
||||
if (size == 2) {
|
||||
auto p = reinterpret_cast<const uint16_t*>(argument);
|
||||
amd::half2float(*p, &arg);
|
||||
}
|
||||
const float fArg = size == 2 ?
|
||||
amd::half2float(*(reinterpret_cast<const uint16_t *>(argument))) :
|
||||
*(reinterpret_cast<const float *>(argument));
|
||||
static const char* fSpecifiers = "eEfgGa";
|
||||
std::string fmtF = fmt;
|
||||
size_t posS = fmtF.find_first_of("%");
|
||||
@@ -303,7 +301,6 @@ size_t PrintfDbg::outputArgument(const std::string& fmt, bool printFloat, size_t
|
||||
if (posS != std::string::npos && posE != std::string::npos) {
|
||||
fmtF.replace(posS + 1, posE - posS, "s");
|
||||
}
|
||||
float fArg = *(reinterpret_cast<const float*>(&arg));
|
||||
float fSign = copysign(1.0, fArg);
|
||||
if (isinf(fArg) && !isnan(fArg)) {
|
||||
if (fSign < 0) {
|
||||
@@ -333,9 +330,13 @@ size_t PrintfDbg::outputArgument(const std::string& fmt, bool printFloat, size_t
|
||||
hhFmt.erase(hhFmt.find_first_of("h"), 2);
|
||||
amd::Os::printf(hhFmt.data(), *(reinterpret_cast<const unsigned char*>(argument)));
|
||||
} else if (hlModifier) {
|
||||
amd::Os::printf(hlFmt.data(), *argument);
|
||||
amd::Os::printf(hlFmt.data(), size == 2 ?
|
||||
*(reinterpret_cast<const uint16_t *>(argument)):
|
||||
*(reinterpret_cast<const uint32_t *>(argument)));
|
||||
} else {
|
||||
amd::Os::printf(fmt.data(), *argument);
|
||||
amd::Os::printf(fmt.data(), size == 2 ?
|
||||
*(reinterpret_cast<const uint16_t *>(argument)):
|
||||
*(reinterpret_cast<const uint32_t *>(argument)));
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -403,13 +404,13 @@ void PrintfDbg::outputDbgBuffer(const device::PrintfInfo& info, const uint32_t*
|
||||
fmt = str.substr(pos, posEnd - pos);
|
||||
fmt.erase(posStart - pos - 1, 1);
|
||||
pos = posStart = posEnd;
|
||||
outputArgument(sepStr, false, ConstStr, reinterpret_cast<const uint32_t*>(fmt.data()));
|
||||
outputArgument(sepStr, false, ConstStr, fmt.data());
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
} else if (pos < str.length()) {
|
||||
outputArgument(sepStr, false, ConstStr,
|
||||
reinterpret_cast<const uint32_t*>((str.substr(pos)).data()));
|
||||
str.substr(pos).data());
|
||||
}
|
||||
} while (posStart != std::string::npos);
|
||||
|
||||
@@ -473,11 +474,11 @@ void PrintfDbg::outputDbgBuffer(const device::PrintfInfo& info, const uint32_t*
|
||||
const char* t = reinterpret_cast<const char*>(s);
|
||||
|
||||
// Output the vector separator
|
||||
outputArgument(sepStr, false, ConstStr, reinterpret_cast<const uint32_t*>(Separator));
|
||||
outputArgument(sepStr, false, ConstStr, Separator);
|
||||
|
||||
// Output the next element
|
||||
outputArgument(elementStr, printFloat, elemSize,
|
||||
reinterpret_cast<const uint32_t*>(&t[k + e * elemSize]));
|
||||
&t[k + e * elemSize]);
|
||||
}
|
||||
i += (amd::alignUp(info.arguments_[j], sizeof(uint32_t))) / sizeof(uint32_t);
|
||||
}
|
||||
@@ -486,7 +487,7 @@ void PrintfDbg::outputDbgBuffer(const device::PrintfInfo& info, const uint32_t*
|
||||
|
||||
if (pos != std::string::npos) {
|
||||
fmt = str.substr(pos, str.size() - pos);
|
||||
outputArgument(sepStr, false, ConstStr, reinterpret_cast<const uint32_t*>(fmt.data()));
|
||||
outputArgument(sepStr, false, ConstStr, fmt.data());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -118,7 +118,7 @@ class PrintfDbg : public amd::HeapObject {
|
||||
size_t outputArgument(const std::string& fmt, //!< Format strint
|
||||
bool printFloat, //!< Argument is a float value
|
||||
size_t size, //!< Argument's size
|
||||
const uint32_t* argument //!< Argument's location
|
||||
const void* argument //!< Argument's location
|
||||
) const;
|
||||
|
||||
//! Displays the PrintfDbg
|
||||
|
||||
@@ -135,17 +135,16 @@ static constexpr size_t ConstStr = 0xffffffff;
|
||||
static constexpr char Separator[] = ",\0";
|
||||
|
||||
size_t PrintfDbg::outputArgument(const std::string& fmt, bool printFloat, size_t size,
|
||||
const uint32_t* argument) const {
|
||||
const void* argument) const {
|
||||
// Serialize the output to the screen
|
||||
// amd::ScopedLock k(dev().lockAsyncOps());
|
||||
|
||||
size_t copiedBytes = size;
|
||||
// Print the string argument, using standard PrintfDbg()
|
||||
if (checkString(fmt.c_str())) {
|
||||
// copiedBytes should be as number of printed chars
|
||||
copiedBytes = 0;
|
||||
//(null) should be printed
|
||||
if (*argument == 0) {
|
||||
if (*(reinterpret_cast<const unsigned char*>(argument)) == 0) {
|
||||
amd::Os::printf(fmt.data(), 0);
|
||||
// copiedBytes = strlen("(null)")
|
||||
copiedBytes = 6;
|
||||
@@ -180,11 +179,9 @@ size_t PrintfDbg::outputArgument(const std::string& fmt, bool printFloat, size_t
|
||||
case 2:
|
||||
case 4:
|
||||
if (printFloat) {
|
||||
uint32_t arg = *argument;
|
||||
if (size == 2) {
|
||||
auto p = reinterpret_cast<const uint16_t*>(argument);
|
||||
amd::half2float(*p, &arg);
|
||||
}
|
||||
const float fArg = size == 2 ?
|
||||
amd::half2float(*(reinterpret_cast<const uint16_t *>(argument))) :
|
||||
*(reinterpret_cast<const float *>(argument));
|
||||
static const char* fSpecifiers = "eEfgGa";
|
||||
std::string fmtF = fmt;
|
||||
size_t posS = fmtF.find_first_of("%");
|
||||
@@ -192,7 +189,6 @@ size_t PrintfDbg::outputArgument(const std::string& fmt, bool printFloat, size_t
|
||||
if (posS != std::string::npos && posE != std::string::npos) {
|
||||
fmtF.replace(posS + 1, posE - posS, "s");
|
||||
}
|
||||
float fArg = *(reinterpret_cast<const float*>(&arg));
|
||||
float fSign = copysign(1.0, fArg);
|
||||
if (std::isinf(fArg) && !std::isnan(fArg)) {
|
||||
if (fSign < 0) {
|
||||
@@ -223,9 +219,13 @@ size_t PrintfDbg::outputArgument(const std::string& fmt, bool printFloat, size_t
|
||||
hhFmt.erase(hhFmt.find_first_of("h"), 2);
|
||||
amd::Os::printf(hhFmt.data(), *(reinterpret_cast<const unsigned char*>(argument)));
|
||||
} else if (hlModifier) {
|
||||
amd::Os::printf(hlFmt.data(), *argument);
|
||||
amd::Os::printf(hlFmt.data(), size == 2 ?
|
||||
*(reinterpret_cast<const uint16_t *>(argument)):
|
||||
*(reinterpret_cast<const uint32_t *>(argument)));
|
||||
} else {
|
||||
amd::Os::printf(fmt.data(), *argument);
|
||||
amd::Os::printf(fmt.data(), size == 2 ?
|
||||
*(reinterpret_cast<const uint16_t *>(argument)):
|
||||
*(reinterpret_cast<const uint32_t *>(argument)));
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -295,13 +295,13 @@ void PrintfDbg::outputDbgBuffer(const device::PrintfInfo& info, const uint32_t*
|
||||
fmt = str.substr(pos, posEnd - pos);
|
||||
fmt.erase(posStart - pos - 1, 1);
|
||||
pos = posStart = posEnd;
|
||||
outputArgument(sepStr, false, ConstStr, reinterpret_cast<const uint32_t*>(fmt.data()));
|
||||
outputArgument(sepStr, false, ConstStr, fmt.data());
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
} else if (pos < str.length()) {
|
||||
outputArgument(sepStr, false, ConstStr,
|
||||
reinterpret_cast<const uint32_t*>((str.substr(pos)).data()));
|
||||
str.substr(pos).data());
|
||||
}
|
||||
} while (posStart != std::string::npos);
|
||||
|
||||
|
||||
@@ -103,7 +103,7 @@ class PrintfDbg : public amd::HeapObject {
|
||||
size_t outputArgument(const std::string& fmt, //!< Format strint
|
||||
bool printFloat, //!< Argument is a float value
|
||||
size_t size, //!< Argument's size
|
||||
const uint32_t* argument //!< Argument's location
|
||||
const void* argument //!< Argument's location
|
||||
) const;
|
||||
|
||||
//! Displays the PrintfDbg
|
||||
|
||||
+11
-7
@@ -238,10 +238,9 @@ template <typename lambda> class ScopeGuard {
|
||||
#define MAKE_SCOPE_GUARD(name, ...) \
|
||||
MAKE_SCOPE_GUARD_HELPER(XCONCAT(scopeGuardLambda, __COUNTER__), name, __VA_ARGS__)
|
||||
|
||||
|
||||
// utility function to convert half precision to float to a
|
||||
// single precision value.
|
||||
inline void half2float(uint16_t Val, uint32_t *Res) {
|
||||
inline float half2float(const uint16_t Val) {
|
||||
constexpr uint32_t halfExpoentMask = 0x7c00;
|
||||
constexpr uint32_t halfFractionMask = 0x03ff;
|
||||
constexpr uint32_t floatExponentBias = 127;
|
||||
@@ -252,17 +251,21 @@ inline void half2float(uint16_t Val, uint32_t *Res) {
|
||||
uint32_t exponent = (Val & halfExpoentMask) >> 10;
|
||||
uint32_t fraction = ((uint32_t)(Val & halfFractionMask))
|
||||
<< 13; // Aligning half fraction to float
|
||||
union {
|
||||
uint32_t u32Arg;
|
||||
float fArg;
|
||||
};
|
||||
// Handling special cases
|
||||
if (exponent == 0x1f) { // NaN or Infinity
|
||||
// When all exponent bits are 1, the value is either Infinity or NaN
|
||||
// For NaN, the fraction part should also be non-zero.
|
||||
*Res = signBit | 0x7f800000 |
|
||||
u32Arg = signBit | 0x7f800000 |
|
||||
fraction; // setting exponent to all 1's and keeping the fraction
|
||||
return;
|
||||
return fArg;
|
||||
} else if (exponent == 0) { // Subnormal numbers or zero
|
||||
if (fraction == 0) {
|
||||
*Res = signBit; // Plus or minus zero
|
||||
return;
|
||||
u32Arg = signBit; // Plus or minus zero
|
||||
return fArg;
|
||||
} else {
|
||||
// Normalize subnormal number
|
||||
while ((fraction & (1 << 23)) == 0) {
|
||||
@@ -277,7 +280,8 @@ inline void half2float(uint16_t Val, uint32_t *Res) {
|
||||
uint32_t floatExponent =
|
||||
((exponent + floatExponentBias - halfExponentBias) & 0xff)
|
||||
<< floatExponentShift;
|
||||
*Res = signBit | floatExponent | fraction;
|
||||
u32Arg = signBit | floatExponent | fraction;
|
||||
return fArg;
|
||||
}
|
||||
|
||||
/*@}*/} // namespace amd
|
||||
|
||||
새 이슈에서 참조
사용자 차단