Promote cns argument to int64_t to ensure correctness

Some operations such as cns(-1) would end up emitting
the wrong thing, because the -1 literal would be interpreted as
int32_t and only four bytes would get copied across by memcpy.
The result is that cns(-1) would in fact emit the constant
4294967295 (= 2^32-1) which is bound to lead to wrong code.

A former workaround involved using cns(-1LL). I removed this
use case to show that this is now kosher (and added a test to
show that nothing broke - use TRACE=hhir:2 to check).
Esse commit está contido em:
Eric Caruso
2013-07-01 11:24:13 -07:00
commit de Sara Golemon
commit 5d27fbcc69
4 arquivos alterados com 35 adições e 2 exclusões
+17 -1
Ver Arquivo
@@ -160,9 +160,25 @@ struct ConstData : IRExtraData {
"Constant data was larger than supported");
static_assert(std::is_pod<T>::value,
"Constant data wasn't a pod?");
std::memcpy(&m_dataBits, &data, sizeof data);
const auto toCopy = promoteIfNeeded(data);
std::memcpy(&m_dataBits, &toCopy, sizeof(toCopy));
}
template<typename T>
struct needsPromotion {
static constexpr bool value = std::is_integral<T>::value ||
std::is_same<T,bool>::value ||
std::is_enum<T>::value;
};
template<class T>
typename std::enable_if<needsPromotion<T>::value, int64_t>::type
promoteIfNeeded(T t) { return t; }
template<class T>
typename std::enable_if<!needsPromotion<T>::value, T>::type
promoteIfNeeded(T t) { return t; }
template<class T>
T as() const {
T ret;
+1 -1
Ver Arquivo
@@ -3251,7 +3251,7 @@ void HhbcTranslator::emitMod() {
SSATmp *res = m_tb->cond(
curFunc(),
[&] (Block* taken) {
SSATmp* negone = gen(OpEq, tr, cns(-1LL));
SSATmp* negone = gen(OpEq, tr, cns(-1));
gen(JmpNZero, taken, negone);
},
[&] {
+15
Ver Arquivo
@@ -0,0 +1,15 @@
<?php
function int_min() {
return ~PHP_INT_MAX;
}
function int_negone() {
return -1;
}
function main() {
var_dump(int_min() % -1);
var_dump(int_min() % int_negone());
}
main();
+2
Ver Arquivo
@@ -0,0 +1,2 @@
int(0)
int(0)