Implement operator-based implicit type conversions.
git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@20724 e7fa87d3-cd2b-0410-9028-fcbf551c1848
This commit is contained in:
parent
ef8ae2e345
commit
4b67103b02
@ -11,7 +11,51 @@ out vec4 o;
|
|||||||
|
|
||||||
uniform mat4x2 m;
|
uniform mat4x2 m;
|
||||||
|
|
||||||
|
struct s {
|
||||||
|
float f;
|
||||||
|
};
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
mat2x3 m23 = mat2x3(m);
|
mat2x3 m23 = mat2x3(m);
|
||||||
|
|
||||||
|
int a;
|
||||||
|
bool b;
|
||||||
|
s sv = s(a);
|
||||||
|
float[2] ia = float[2](3, i.y);
|
||||||
|
float f1 = 1;
|
||||||
|
float f = a;
|
||||||
|
f = a;
|
||||||
|
ivec3 iv3;
|
||||||
|
vec3 v3 = iv3;
|
||||||
|
f = f + a;
|
||||||
|
f = a - f;
|
||||||
|
f += a;
|
||||||
|
f = a - f;
|
||||||
|
v3 *= iv3;
|
||||||
|
v3 = iv3 / 2.0;
|
||||||
|
v3 = 3.0 * iv3;
|
||||||
|
v3 = 2 * v3;
|
||||||
|
v3 = v3 - 2;
|
||||||
|
if (f < a ||
|
||||||
|
a <= f ||
|
||||||
|
f > a ||
|
||||||
|
f >= a ||
|
||||||
|
a == f ||
|
||||||
|
f != a);
|
||||||
|
f = b ? a : f;
|
||||||
|
f = b ? f : a;
|
||||||
|
f = b ? a : a;
|
||||||
|
s news = sv;
|
||||||
|
|
||||||
|
i.xy + i.xyz; // ERROR
|
||||||
|
m * i.xyz; // ERROR
|
||||||
|
m + i; // ERROR
|
||||||
|
int aoeu = 1.0; // ERROR
|
||||||
|
f = b; // ERROR
|
||||||
|
f = a + b; // ERROR
|
||||||
|
f = b * a; // ERROR
|
||||||
|
b = a; // ERROR
|
||||||
|
b = b + f; // ERROR
|
||||||
|
f |= b; // ERROR
|
||||||
}
|
}
|
||||||
|
@ -93,16 +93,13 @@ TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIn
|
|||||||
case EOpSub:
|
case EOpSub:
|
||||||
case EOpDiv:
|
case EOpDiv:
|
||||||
case EOpMul:
|
case EOpMul:
|
||||||
if (left->getType().getBasicType() == EbtStruct || left->getType().getBasicType() == EbtBool)
|
if (left->getType().getBasicType() == EbtStruct || left->getType().getBasicType() == EbtBool || left->getType().isArray())
|
||||||
return 0;
|
return 0;
|
||||||
default: break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// First try converting the children to compatible types.
|
// First try converting the children to compatible types.
|
||||||
//
|
//
|
||||||
|
|
||||||
if (!(left->getType().getStruct() && right->getType().getStruct())) {
|
|
||||||
TIntermTyped* child = addConversion(op, left->getType(), right);
|
TIntermTyped* child = addConversion(op, left->getType(), right);
|
||||||
if (child)
|
if (child)
|
||||||
right = child;
|
right = child;
|
||||||
@ -113,11 +110,6 @@ TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIn
|
|||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
if (left->getType() != right->getType())
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Need a new node holding things together then. Make
|
// Need a new node holding things together then. Make
|
||||||
@ -228,21 +220,17 @@ TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode,
|
|||||||
case EOpNegative:
|
case EOpNegative:
|
||||||
if (child->getType().getBasicType() == EbtStruct || child->getType().isArray())
|
if (child->getType().getBasicType() == EbtStruct || child->getType().isArray())
|
||||||
return 0;
|
return 0;
|
||||||
default: break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Do we need to promote the operand?
|
// Do we need to promote the operand?
|
||||||
//
|
//
|
||||||
// Note: Implicit promotions were removed from the language.
|
|
||||||
//
|
|
||||||
TBasicType newType = EbtVoid;
|
TBasicType newType = EbtVoid;
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case EOpConstructInt: newType = EbtInt; break;
|
case EOpConstructInt: newType = EbtInt; break;
|
||||||
case EOpConstructBool: newType = EbtBool; break;
|
case EOpConstructBool: newType = EbtBool; break;
|
||||||
case EOpConstructFloat: newType = EbtFloat; break;
|
case EOpConstructFloat: newType = EbtFloat; break;
|
||||||
case EOpConstructDouble: newType = EbtDouble; break;
|
case EOpConstructDouble: newType = EbtDouble; break;
|
||||||
default: break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newType != EbtVoid) {
|
if (newType != EbtVoid) {
|
||||||
@ -261,8 +249,8 @@ TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode,
|
|||||||
case EOpConstructInt:
|
case EOpConstructInt:
|
||||||
case EOpConstructBool:
|
case EOpConstructBool:
|
||||||
case EOpConstructFloat:
|
case EOpConstructFloat:
|
||||||
|
case EOpConstructDouble:
|
||||||
return child;
|
return child;
|
||||||
default: break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TIntermConstantUnion *childTempConstant = 0;
|
TIntermConstantUnion *childTempConstant = 0;
|
||||||
@ -370,11 +358,14 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
|
|||||||
if (type.isArray() || node->getType().isArray())
|
if (type.isArray() || node->getType().isArray())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
// Note: callers are responsible for other aspects of shape,
|
||||||
|
// like vector and matrix sizes.
|
||||||
|
|
||||||
TBasicType promoteTo;
|
TBasicType promoteTo;
|
||||||
|
|
||||||
switch (op) {
|
switch (op) {
|
||||||
//
|
//
|
||||||
// Explicit conversions
|
// Explicit conversions (unary operations)
|
||||||
//
|
//
|
||||||
case EOpConstructBool:
|
case EOpConstructBool:
|
||||||
promoteTo = EbtBool;
|
promoteTo = EbtBool;
|
||||||
@ -385,31 +376,83 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
|
|||||||
case EOpConstructInt:
|
case EOpConstructInt:
|
||||||
promoteTo = EbtInt;
|
promoteTo = EbtInt;
|
||||||
break;
|
break;
|
||||||
default:
|
|
||||||
//
|
//
|
||||||
// implicit conversions were removed from the language.
|
// List all the binary ops that can implicitly convert one operand to the other's type;
|
||||||
//
|
// This implements the 'policy' for implicit type conversion.
|
||||||
if (type.getBasicType() != node->getType().getBasicType())
|
|
||||||
return 0;
|
|
||||||
//
|
|
||||||
// Size and structure could still differ, but that's
|
|
||||||
// handled by operator promotion.
|
|
||||||
//
|
//
|
||||||
|
case EOpLessThan:
|
||||||
|
case EOpGreaterThan:
|
||||||
|
case EOpLessThanEqual:
|
||||||
|
case EOpGreaterThanEqual:
|
||||||
|
case EOpEqual:
|
||||||
|
case EOpNotEqual:
|
||||||
|
|
||||||
|
case EOpAdd:
|
||||||
|
case EOpSub:
|
||||||
|
case EOpMul:
|
||||||
|
case EOpDiv:
|
||||||
|
|
||||||
|
case EOpVectorTimesScalar:
|
||||||
|
case EOpVectorTimesMatrix:
|
||||||
|
case EOpMatrixTimesVector:
|
||||||
|
case EOpMatrixTimesScalar:
|
||||||
|
|
||||||
|
case EOpAssign:
|
||||||
|
case EOpAddAssign:
|
||||||
|
case EOpSubAssign:
|
||||||
|
case EOpMulAssign:
|
||||||
|
case EOpVectorTimesScalarAssign:
|
||||||
|
case EOpMatrixTimesScalarAssign:
|
||||||
|
case EOpDivAssign:
|
||||||
|
case EOpModAssign:
|
||||||
|
|
||||||
|
case EOpSequence:
|
||||||
|
case EOpConstructStruct:
|
||||||
|
|
||||||
|
if (type.getBasicType() == node->getType().getBasicType())
|
||||||
return node;
|
return node;
|
||||||
|
|
||||||
|
if (canImplicitlyPromote(node->getType().getBasicType(), type.getBasicType()))
|
||||||
|
promoteTo = type.getBasicType();
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// default is to require a match; all exceptions should have case statements above
|
||||||
|
|
||||||
|
if (type.getBasicType() == node->getType().getBasicType())
|
||||||
|
return node;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node->getAsConstantUnion()) {
|
if (node->getAsConstantUnion()) {
|
||||||
|
|
||||||
return (promoteConstantUnion(promoteTo, node->getAsConstantUnion()));
|
return (promoteConstantUnion(promoteTo, node->getAsConstantUnion()));
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
//
|
//
|
||||||
// Add a new newNode for the conversion.
|
// Add a new newNode for the conversion.
|
||||||
//
|
//
|
||||||
TIntermUnary* newNode = 0;
|
TIntermUnary* newNode = 0;
|
||||||
|
|
||||||
TOperator newOp = EOpNull;
|
TOperator newOp = EOpNull;
|
||||||
|
|
||||||
|
// This is 'mechanism' here, it does any conversion told. The policy comes
|
||||||
|
// from the shader or the above code.
|
||||||
switch (promoteTo) {
|
switch (promoteTo) {
|
||||||
|
case EbtDouble:
|
||||||
|
//switch (node->getBasicType()) {
|
||||||
|
//case EbtInt: newOp = EOpConvIntToDouble; break;
|
||||||
|
//case EbtBool: newOp = EOpConvBoolToDouble; break;
|
||||||
|
//case EbtFloat: newOp = EOpConvFloatToDouble; break;
|
||||||
|
//default:
|
||||||
|
infoSink.info.message(EPrefixInternalError, "Bad promotion node", node->getLine());
|
||||||
|
return 0;
|
||||||
|
//}
|
||||||
|
break;
|
||||||
case EbtFloat:
|
case EbtFloat:
|
||||||
switch (node->getBasicType()) {
|
switch (node->getBasicType()) {
|
||||||
case EbtInt: newOp = EOpConvIntToFloat; break;
|
case EbtInt: newOp = EOpConvIntToFloat; break;
|
||||||
@ -451,6 +494,55 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// See if the 'from' type is allowed to be implicitly converted to the
|
||||||
|
// 'to' type. This is not about vector/array/struct, only about basic type.
|
||||||
|
//
|
||||||
|
bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to)
|
||||||
|
{
|
||||||
|
if (profile == EEsProfile || version == 110)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
switch (to) {
|
||||||
|
case EbtDouble:
|
||||||
|
switch (from) {
|
||||||
|
case EbtInt:
|
||||||
|
case EbtUint:
|
||||||
|
case EbtFloat:
|
||||||
|
case EbtDouble:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case EbtFloat:
|
||||||
|
switch (from) {
|
||||||
|
case EbtInt:
|
||||||
|
case EbtUint:
|
||||||
|
case EbtFloat:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case EbtUint:
|
||||||
|
switch (from) {
|
||||||
|
case EbtInt:
|
||||||
|
case EbtUint:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case EbtInt:
|
||||||
|
switch (from) {
|
||||||
|
case EbtInt:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Safe way to combine two nodes into an aggregate. Works with null pointers,
|
// Safe way to combine two nodes into an aggregate. Works with null pointers,
|
||||||
// a node that's not a aggregate yet, etc.
|
// a node that's not a aggregate yet, etc.
|
||||||
|
@ -1326,11 +1326,12 @@ TIntermTyped* TParseContext::constructBuiltIn(const TType* type, TOperator op, T
|
|||||||
//
|
//
|
||||||
TIntermTyped* TParseContext::constructStruct(TIntermNode* node, TType* type, int paramCount, TSourceLoc line, bool subset)
|
TIntermTyped* TParseContext::constructStruct(TIntermNode* node, TType* type, int paramCount, TSourceLoc line, bool subset)
|
||||||
{
|
{
|
||||||
if (*type == node->getAsTyped()->getType()) {
|
TIntermNode* converted = intermediate.addConversion(EOpConstructStruct, *type, node->getAsTyped());
|
||||||
|
if (converted->getAsTyped()->getType() == *type) {
|
||||||
if (subset)
|
if (subset)
|
||||||
return node->getAsTyped();
|
return converted->getAsTyped();
|
||||||
else
|
else
|
||||||
return intermediate.setAggregateOperator(node->getAsTyped(), EOpConstructStruct, line);
|
return intermediate.setAggregateOperator(converted->getAsTyped(), EOpConstructStruct, line);
|
||||||
} else {
|
} else {
|
||||||
error(line, "", "constructor", "cannot convert parameter %d from '%s' to '%s'", paramCount,
|
error(line, "", "constructor", "cannot convert parameter %d from '%s' to '%s'", paramCount,
|
||||||
node->getAsTyped()->getType().getCompleteTypeString().c_str(), type->getCompleteTypeString().c_str());
|
node->getAsTyped()->getType().getCompleteTypeString().c_str(), type->getCompleteTypeString().c_str());
|
||||||
|
@ -89,7 +89,7 @@ TPoolAllocator* PerProcessGPA = 0;
|
|||||||
bool InitializeSymbolTable(TBuiltInStrings* BuiltInStrings, int version, EProfile profile, EShLanguage language, TInfoSink& infoSink,
|
bool InitializeSymbolTable(TBuiltInStrings* BuiltInStrings, int version, EProfile profile, EShLanguage language, TInfoSink& infoSink,
|
||||||
const TBuiltInResource* resources, TSymbolTable* symbolTables)
|
const TBuiltInResource* resources, TSymbolTable* symbolTables)
|
||||||
{
|
{
|
||||||
TIntermediate intermediate(infoSink);
|
TIntermediate intermediate(infoSink, version, profile);
|
||||||
TSymbolTable* symbolTable;
|
TSymbolTable* symbolTable;
|
||||||
|
|
||||||
if (resources)
|
if (resources)
|
||||||
@ -509,7 +509,7 @@ int ShCompile(
|
|||||||
version = defaultVersion;
|
version = defaultVersion;
|
||||||
bool goodProfile = DeduceProfile(compiler->infoSink, version, profile);
|
bool goodProfile = DeduceProfile(compiler->infoSink, version, profile);
|
||||||
|
|
||||||
TIntermediate intermediate(compiler->infoSink);
|
TIntermediate intermediate(compiler->infoSink, version, profile);
|
||||||
|
|
||||||
SetupBuiltinSymbolTable(version, profile);
|
SetupBuiltinSymbolTable(version, profile);
|
||||||
TSymbolTable symbolTable(*SharedSymbolTables[MapVersionToIndex(version)]
|
TSymbolTable symbolTable(*SharedSymbolTables[MapVersionToIndex(version)]
|
||||||
|
@ -1073,9 +1073,6 @@ conditional_expression
|
|||||||
parseContext.recover();
|
parseContext.recover();
|
||||||
|
|
||||||
$$ = parseContext.intermediate.addSelection($1, $3, $5, $2.line);
|
$$ = parseContext.intermediate.addSelection($1, $3, $5, $2.line);
|
||||||
if ($3->getType() != $5->getType())
|
|
||||||
$$ = 0;
|
|
||||||
|
|
||||||
if ($$ == 0) {
|
if ($$ == 0) {
|
||||||
parseContext.binaryOpError($2.line, ":", $3->getCompleteString(), $5->getCompleteString());
|
parseContext.binaryOpError($2.line, ":", $3->getCompleteString(), $5->getCompleteString());
|
||||||
parseContext.recover();
|
parseContext.recover();
|
||||||
|
@ -38,6 +38,7 @@
|
|||||||
#include "../Include/intermediate.h"
|
#include "../Include/intermediate.h"
|
||||||
#include "../Public/ShaderLang.h"
|
#include "../Public/ShaderLang.h"
|
||||||
#include "SymbolTable.h"
|
#include "SymbolTable.h"
|
||||||
|
#include "Versions.h"
|
||||||
|
|
||||||
struct TVectorFields {
|
struct TVectorFields {
|
||||||
int offsets[4];
|
int offsets[4];
|
||||||
@ -52,13 +53,14 @@ class TIntermediate {
|
|||||||
public:
|
public:
|
||||||
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
|
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
|
||||||
|
|
||||||
TIntermediate(TInfoSink& i) : infoSink(i) { }
|
TIntermediate(TInfoSink& i, int v, EProfile p) : infoSink(i), version(v), profile(p) { }
|
||||||
TIntermSymbol* addSymbol(int Id, const TString&, const TType&, TSourceLoc);
|
TIntermSymbol* addSymbol(int Id, const TString&, const TType&, TSourceLoc);
|
||||||
TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*);
|
TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*);
|
||||||
TIntermTyped* addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc, TSymbolTable&);
|
TIntermTyped* addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc, TSymbolTable&);
|
||||||
TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc);
|
TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc);
|
||||||
TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc);
|
TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc);
|
||||||
TIntermTyped* addUnaryMath(TOperator op, TIntermNode* child, TSourceLoc, TSymbolTable&);
|
TIntermTyped* addUnaryMath(TOperator op, TIntermNode* child, TSourceLoc, TSymbolTable&);
|
||||||
|
bool canImplicitlyPromote(TBasicType from, TBasicType to);
|
||||||
TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right, TSourceLoc);
|
TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right, TSourceLoc);
|
||||||
TIntermAggregate* makeAggregate(TIntermNode* node, TSourceLoc);
|
TIntermAggregate* makeAggregate(TIntermNode* node, TSourceLoc);
|
||||||
TIntermAggregate* setAggregateOperator(TIntermNode*, TOperator, TSourceLoc);
|
TIntermAggregate* setAggregateOperator(TIntermNode*, TOperator, TSourceLoc);
|
||||||
@ -79,6 +81,8 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
TInfoSink& infoSink;
|
TInfoSink& infoSink;
|
||||||
|
EProfile profile;
|
||||||
|
int version;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void operator=(TIntermediate&); // prevent assignments
|
void operator=(TIntermediate&); // prevent assignments
|
||||||
|
Loading…
x
Reference in New Issue
Block a user