Handle buffer references vs 'const'
Allow constructors to and from references to be constant folded. Section 4.3.3 says constructors whose arguments are all constant expressions must fold. Disallow 'const' on buffer reference types. It is not a 'non-void transparent basic data type' (it is not considered 'basic'). Handle buffer reference constants (which can be assigned to a non-const reference, or can be further folded to another type of constant) by converting to 'constructor(uint64_t constant)' in addConversion. Disallow == and != operators on reference types.
This commit is contained in:
parent
d90d548161
commit
be63facd80
13 changed files with 1271 additions and 1099 deletions
|
|
@ -941,6 +941,10 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TType& returnType)
|
|||
newConstArray[i].setDConst(unionArray[i].getDConst()); break;
|
||||
case EOpConvDoubleToFloat:
|
||||
newConstArray[i].setDConst(unionArray[i].getDConst()); break;
|
||||
case EOpConvPtrToUint64:
|
||||
case EOpConvUint64ToPtr:
|
||||
case EOpConstructReference:
|
||||
newConstArray[i].setU64Const(unionArray[i].getU64Const()); break;
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -725,6 +725,19 @@ TIntermTyped* TIntermediate::createConversion(TBasicType convertTo, TIntermTyped
|
|||
return newNode;
|
||||
}
|
||||
|
||||
// Convert a constant that is a reference type to a uint64_t constant plus a
|
||||
// constructor instruction. This is needed because SPIR-V doesn't support
|
||||
// OpConstant on pointer types.
|
||||
TIntermTyped* TIntermediate::addConstantReferenceConversion(TIntermTyped* node)
|
||||
{
|
||||
if (node->getType().getBasicType() == EbtReference && node->getAsConstantUnion()) {
|
||||
const TType &type = node->getType();
|
||||
node = addBuiltInFunctionCall(node->getLoc(), EOpConvPtrToUint64, true, node, TType(EbtUint64));
|
||||
node = addUnaryNode(EOpConstructReference, node, node->getLoc(), type);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
TIntermTyped* TIntermediate::addConversion(TBasicType convertTo, TIntermTyped* node) const
|
||||
{
|
||||
return createConversion(convertTo, node);
|
||||
|
|
@ -743,7 +756,7 @@ TIntermTyped* TIntermediate::addConversion(TBasicType convertTo, TIntermTyped* n
|
|||
// Returns the converted pair of nodes.
|
||||
// Returns <nullptr, nullptr> when there is no conversion.
|
||||
std::tuple<TIntermTyped*, TIntermTyped*>
|
||||
TIntermediate::addConversion(TOperator op, TIntermTyped* node0, TIntermTyped* node1) const
|
||||
TIntermediate::addConversion(TOperator op, TIntermTyped* node0, TIntermTyped* node1)
|
||||
{
|
||||
if (!isConversionAllowed(op, node0) || !isConversionAllowed(op, node1))
|
||||
return std::make_tuple(nullptr, nullptr);
|
||||
|
|
@ -762,6 +775,9 @@ TIntermediate::addConversion(TOperator op, TIntermTyped* node0, TIntermTyped* no
|
|||
return std::make_tuple(node0, node1);
|
||||
}
|
||||
|
||||
node0 = addConstantReferenceConversion(node0);
|
||||
node1 = addConstantReferenceConversion(node1);
|
||||
|
||||
auto promoteTo = std::make_tuple(EbtNumTypes, EbtNumTypes);
|
||||
|
||||
switch (op) {
|
||||
|
|
@ -876,11 +892,13 @@ TIntermediate::addConversion(TOperator op, TIntermTyped* node0, TIntermTyped* no
|
|||
//
|
||||
// Return nullptr if a conversion can't be done.
|
||||
//
|
||||
TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TIntermTyped* node) const
|
||||
TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TIntermTyped* node)
|
||||
{
|
||||
if (!isConversionAllowed(op, node))
|
||||
return nullptr;
|
||||
|
||||
node = addConstantReferenceConversion(node);
|
||||
|
||||
// Otherwise, if types are identical, no problem
|
||||
if (type == node->getType())
|
||||
return node;
|
||||
|
|
|
|||
|
|
@ -4435,6 +4435,12 @@ void TParseContext::opaqueCheck(const TSourceLoc& loc, const TType& type, const
|
|||
error(loc, "can't use with samplers or structs containing samplers", op, "");
|
||||
}
|
||||
|
||||
void TParseContext::referenceCheck(const TSourceLoc& loc, const TType& type, const char* op)
|
||||
{
|
||||
if (containsFieldWithBasicType(type, EbtReference))
|
||||
error(loc, "can't use with reference types", op, "");
|
||||
}
|
||||
|
||||
void TParseContext::storage16BitAssignmentCheck(const TSourceLoc& loc, const TType& type, const char* op)
|
||||
{
|
||||
if (type.getBasicType() == EbtStruct && containsFieldWithBasicType(type, EbtFloat16))
|
||||
|
|
@ -6290,6 +6296,9 @@ TIntermNode* TParseContext::declareVariable(const TSourceLoc& loc, TString& iden
|
|||
#ifdef NV_EXTENSIONS
|
||||
accStructNVCheck(loc, type, identifier);
|
||||
#endif
|
||||
if (type.getQualifier().storage == EvqConst && type.containsBasicType(EbtReference)) {
|
||||
error(loc, "variables with reference type can't have qualifier 'const'", "qualifier", "");
|
||||
}
|
||||
|
||||
if (type.getQualifier().storage != EvqUniform && type.getQualifier().storage != EvqBuffer) {
|
||||
if (type.containsBasicType(EbtFloat16))
|
||||
|
|
@ -6518,7 +6527,11 @@ TIntermNode* TParseContext::executeInitializer(const TSourceLoc& loc, TIntermTyp
|
|||
// We either have a folded constant in getAsConstantUnion, or we have to use
|
||||
// the initializer's subtree in the AST to represent the computation of a
|
||||
// specialization constant.
|
||||
assert(initializer->getAsConstantUnion() || initializer->getType().getQualifier().isSpecConstant());
|
||||
// A third case arises when a reference type is made non-constant due to
|
||||
// addConstantReferenceConversion, but reference types can't be const, so
|
||||
// this is an error.
|
||||
assert(initializer->getAsConstantUnion() || initializer->getType().getQualifier().isSpecConstant() ||
|
||||
initializer->getType().getBasicType() == EbtReference);
|
||||
if (initializer->getAsConstantUnion())
|
||||
variable->setConstArray(initializer->getAsConstantUnion()->getConstArray());
|
||||
else {
|
||||
|
|
@ -6860,7 +6873,7 @@ TIntermTyped* TParseContext::constructBuiltIn(const TType& type, TOperator op, T
|
|||
|
||||
case EOpConstructUint64:
|
||||
if (type.isScalar() && node->getType().getBasicType() == EbtReference) {
|
||||
TIntermUnary* newNode = intermediate.addUnaryNode(EOpConvPtrToUint64, node, node->getLoc(), type);
|
||||
TIntermTyped* newNode = intermediate.addBuiltInFunctionCall(node->getLoc(), EOpConvPtrToUint64, true, node, type);
|
||||
return newNode;
|
||||
}
|
||||
// fall through
|
||||
|
|
@ -6885,11 +6898,11 @@ TIntermTyped* TParseContext::constructBuiltIn(const TType& type, TOperator op, T
|
|||
case EOpConstructReference:
|
||||
// construct reference from reference
|
||||
if (node->getType().getBasicType() == EbtReference) {
|
||||
newNode = intermediate.addUnaryNode(EOpConstructReference, node, node->getLoc(), type);
|
||||
newNode = intermediate.addBuiltInFunctionCall(node->getLoc(), EOpConstructReference, true, node, type);
|
||||
return newNode;
|
||||
// construct reference from uint64
|
||||
} else if (node->getType().isScalar() && node->getType().getBasicType() == EbtUint64) {
|
||||
TIntermUnary* newNode = intermediate.addUnaryNode(EOpConvUint64ToPtr, node, node->getLoc(), type);
|
||||
TIntermTyped* newNode = intermediate.addBuiltInFunctionCall(node->getLoc(), EOpConvUint64ToPtr, true, node, type);
|
||||
return newNode;
|
||||
} else {
|
||||
return nullptr;
|
||||
|
|
|
|||
|
|
@ -370,6 +370,7 @@ public:
|
|||
void nestedStructCheck(const TSourceLoc&);
|
||||
void arrayObjectCheck(const TSourceLoc&, const TType&, const char* op);
|
||||
void opaqueCheck(const TSourceLoc&, const TType&, const char* op);
|
||||
void referenceCheck(const TSourceLoc&, const TType&, const char* op);
|
||||
void storage16BitAssignmentCheck(const TSourceLoc&, const TType&, const char* op);
|
||||
void specializationCheck(const TSourceLoc&, const TType&, const char* op);
|
||||
void structTypeCheck(const TSourceLoc&, TPublicType&);
|
||||
|
|
|
|||
|
|
@ -613,6 +613,7 @@ equality_expression
|
|||
parseContext.arrayObjectCheck($2.loc, $1->getType(), "array comparison");
|
||||
parseContext.opaqueCheck($2.loc, $1->getType(), "==");
|
||||
parseContext.specializationCheck($2.loc, $1->getType(), "==");
|
||||
parseContext.referenceCheck($2.loc, $1->getType(), "==");
|
||||
$$ = parseContext.handleBinaryMath($2.loc, "==", EOpEqual, $1, $3);
|
||||
if ($$ == 0)
|
||||
$$ = parseContext.intermediate.addConstantUnion(false, $2.loc);
|
||||
|
|
@ -621,6 +622,7 @@ equality_expression
|
|||
parseContext.arrayObjectCheck($2.loc, $1->getType(), "array comparison");
|
||||
parseContext.opaqueCheck($2.loc, $1->getType(), "!=");
|
||||
parseContext.specializationCheck($2.loc, $1->getType(), "!=");
|
||||
parseContext.referenceCheck($2.loc, $1->getType(), "!=");
|
||||
$$ = parseContext.handleBinaryMath($2.loc, "!=", EOpNotEqual, $1, $3);
|
||||
if ($$ == 0)
|
||||
$$ = parseContext.intermediate.addConstantUnion(false, $2.loc);
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
5
glslang/MachineIndependent/localintermediate.h
Executable file → Normal file
5
glslang/MachineIndependent/localintermediate.h
Executable file → Normal file
|
|
@ -495,12 +495,13 @@ public:
|
|||
TIntermSymbol* addSymbol(const TVariable&, const TSourceLoc&);
|
||||
TIntermSymbol* addSymbol(const TType&, const TSourceLoc&);
|
||||
TIntermSymbol* addSymbol(const TIntermSymbol&);
|
||||
TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*) const;
|
||||
std::tuple<TIntermTyped*, TIntermTyped*> addConversion(TOperator op, TIntermTyped* node0, TIntermTyped* node1) const;
|
||||
TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*);
|
||||
std::tuple<TIntermTyped*, TIntermTyped*> addConversion(TOperator op, TIntermTyped* node0, TIntermTyped* node1);
|
||||
TIntermTyped* addUniShapeConversion(TOperator, const TType&, TIntermTyped*);
|
||||
TIntermTyped* addConversion(TBasicType convertTo, TIntermTyped* node) const;
|
||||
void addBiShapeConversion(TOperator, TIntermTyped*& lhsNode, TIntermTyped*& rhsNode);
|
||||
TIntermTyped* addShapeConversion(const TType&, TIntermTyped*);
|
||||
TIntermTyped* addConstantReferenceConversion(TIntermTyped* node);
|
||||
TIntermTyped* addBinaryMath(TOperator, TIntermTyped* left, TIntermTyped* right, TSourceLoc);
|
||||
TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc);
|
||||
TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue