AST: Fix shift conversions, which don't require matching types.

The base and shift amount need to be integers, but not of the same type.
This fixes #1296 and replaces #1297.
This commit is contained in:
John Kessenich 2018-03-15 21:07:35 -06:00
parent 6e899be5ec
commit 647fccaf2f
9 changed files with 1475 additions and 1413 deletions

View file

@ -744,9 +744,6 @@ TIntermediate::addConversion(TOperator op, TIntermTyped* node0, TIntermTyped* no
auto promoteTo = std::make_tuple(EbtNumTypes, EbtNumTypes);
TBasicType type0 = node0->getType().getBasicType();
TBasicType type1 = node1->getType().getBasicType();
switch (op) {
//
// List all the binary ops that can implicitly convert one operand to the other's type;
@ -776,10 +773,10 @@ TIntermediate::addConversion(TOperator op, TIntermTyped* node0, TIntermTyped* no
case EOpSequence: // used by ?:
if (type0 == type1)
if (node0->getBasicType() == node1->getBasicType())
return std::make_tuple(node0, node1);
promoteTo = getConversionDestinatonType(type0, type1, op);
promoteTo = getConversionDestinatonType(node0->getBasicType(), node1->getBasicType(), op);
if (std::get<0>(promoteTo) == EbtNumTypes || std::get<1>(promoteTo) == EbtNumTypes)
return std::make_tuple(nullptr, nullptr);
@ -794,23 +791,25 @@ TIntermediate::addConversion(TOperator op, TIntermTyped* node0, TIntermTyped* no
return std::make_tuple(node0, node1);
break;
// Shifts can have mixed types as long as they are integer and of the same rank,
// without converting.
// There are no conversions needed for GLSL; the shift amount just needs to be an
// integer type, as does the base.
// HLSL can promote bools to ints to make this work.
case EOpLeftShift:
case EOpRightShift:
if (node0->getType() == node1->getType())
return std::make_tuple(node0, node1);
if (isTypeInt(type0) && isTypeInt(type1)) {
if (getTypeRank(type0) == getTypeRank(type1)) {
if (source == EShSourceHlsl) {
TBasicType node0BasicType = node0->getBasicType();
if (node0BasicType == EbtBool)
node0BasicType = EbtInt;
if (node1->getBasicType() == EbtBool)
promoteTo = std::make_tuple(node0BasicType, EbtInt);
else
promoteTo = std::make_tuple(node0BasicType, node1->getBasicType());
} else {
if (isTypeInt(node0->getBasicType()) && isTypeInt(node1->getBasicType()))
return std::make_tuple(node0, node1);
} else {
promoteTo = getConversionDestinatonType(type0, type1, op);
if (std::get<0>(promoteTo) == EbtNumTypes || std::get<1>(promoteTo) == EbtNumTypes)
return std::make_tuple(nullptr, nullptr);
}
} else
return std::make_tuple(nullptr, nullptr);
else
return std::make_tuple(nullptr, nullptr);
}
break;
default:
@ -964,35 +963,24 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
if (type.getBasicType() == node->getType().getBasicType())
return node;
if (canImplicitlyPromote(node->getType().getBasicType(), type.getBasicType(), op))
if (canImplicitlyPromote(node->getBasicType(), type.getBasicType(), op))
promoteTo = type.getBasicType();
else
return nullptr;
break;
// Shifts can have mixed types as long as they are integer and of the same rank,
// without converting.
// It's the left operand's type that determines the resulting type, so no issue
// with assign shift ops either.
// For GLSL, there are no conversions needed; the shift amount just needs to be an
// integer type, as do the base/result.
// HLSL can convert the shift from a bool to an int.
case EOpLeftShiftAssign:
case EOpRightShiftAssign:
{
TBasicType type0 = type.getBasicType();
TBasicType type1 = node->getType().getBasicType();
if (source == EShSourceHlsl && node->getType().getBasicType() == EbtBool) {
promoteTo = type0;
} else {
if (isTypeInt(type0) && isTypeInt(type1)) {
if (getTypeRank(type0) == getTypeRank(type1)) {
return node;
} else {
if (canImplicitlyPromote(type1, type0, op))
promoteTo = type0;
else
return nullptr;
}
} else
if (source == EShSourceHlsl && node->getType().getBasicType() == EbtBool)
promoteTo = type.getBasicType();
else {
if (isTypeInt(type.getBasicType()) && isTypeInt(node->getBasicType()))
return node;
else
return nullptr;
}
break;
@ -1437,9 +1425,7 @@ bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperat
extensionRequested(E_GL_KHX_shader_explicit_arithmetic_types_float32) ||
extensionRequested(E_GL_KHX_shader_explicit_arithmetic_types_float64);
if(explicitTypesEnabled)
{
if(explicitTypesEnabled) {
// integral promotions
if (isIntegralPromotion(from, to)) {
return true;