Non-functional: correctly do GL_EXT_buffer_reference2 semantic checking

See #2366 for detail.
This commit is contained in:
johnkslang 2020-08-07 02:26:04 -06:00
parent 6c37bbbb03
commit d8daeb4323
8 changed files with 1253 additions and 1240 deletions

View File

@ -2,8 +2,12 @@ spv.bufferhandle17_Errors.frag
ERROR: 0:11: 'qualifier' : variables with reference type can't have qualifier 'const'
ERROR: 0:16: 'qualifier' : variables with reference type can't have qualifier 'const'
ERROR: 0:18: '==' : can't use with reference types
ERROR: 0:18: 'buffer reference math' : required extension not requested: GL_EXT_buffer_reference2
ERROR: 0:18: '==' : wrong operand types: no operation '==' exists that takes a left-hand operand of type ' temp reference' and a right operand of type ' temp reference' (or there is no acceptable conversion)
ERROR: 0:19: '!=' : can't use with reference types
ERROR: 4 compilation errors. No code generated.
ERROR: 0:19: 'buffer reference math' : required extension not requested: GL_EXT_buffer_reference2
ERROR: 0:19: '!=' : wrong operand types: no operation '!=' exists that takes a left-hand operand of type ' temp reference' and a right operand of type ' temp reference' (or there is no acceptable conversion)
ERROR: 8 compilation errors. No code generated.
SPIR-V is not generated for failed compile or link

View File

@ -120,7 +120,7 @@ TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIn
return nullptr;
// Convert "reference +/- int" and "reference - reference" to integer math
if ((op == EOpAdd || op == EOpSub) && extensionRequested(E_GL_EXT_buffer_reference2)) {
if (op == EOpAdd || op == EOpSub) {
// No addressing math on struct with unsized array.
if ((left->isReference() && left->getType().getReferentType()->containsUnsizedArray()) ||
@ -140,41 +140,42 @@ TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIn
node = addBuiltInFunctionCall(loc, EOpConvUint64ToPtr, true, node, referenceType);
return node;
}
if (op == EOpAdd && right->isReference() && isTypeInt(left->getBasicType())) {
const TType& referenceType = right->getType();
TIntermConstantUnion* size = addConstantUnion((unsigned long long)computeBufferReferenceTypeSize(right->getType()), loc, true);
right = addBuiltInFunctionCall(loc, EOpConvPtrToUint64, true, right, TType(EbtUint64));
left = createConversion(EbtInt64, left);
left = addBinaryMath(EOpMul, left, size, loc);
TIntermTyped *node = addBinaryMath(op, left, right, loc);
node = addBuiltInFunctionCall(loc, EOpConvUint64ToPtr, true, node, referenceType);
return node;
}
if (op == EOpSub && left->isReference() && right->isReference()) {
TIntermConstantUnion* size = addConstantUnion((long long)computeBufferReferenceTypeSize(left->getType()), loc, true);
left = addBuiltInFunctionCall(loc, EOpConvPtrToUint64, true, left, TType(EbtUint64));
right = addBuiltInFunctionCall(loc, EOpConvPtrToUint64, true, right, TType(EbtUint64));
left = addBuiltInFunctionCall(loc, EOpConvUint64ToInt64, true, left, TType(EbtInt64));
right = addBuiltInFunctionCall(loc, EOpConvUint64ToInt64, true, right, TType(EbtInt64));
left = addBinaryMath(EOpSub, left, right, loc);
TIntermTyped *node = addBinaryMath(EOpDiv, left, size, loc);
return node;
}
// No other math operators supported on references
if (left->isReference() || right->isReference()) {
return nullptr;
}
}
if (op == EOpAdd && right->isReference() && isTypeInt(left->getBasicType())) {
const TType& referenceType = right->getType();
TIntermConstantUnion* size =
addConstantUnion((unsigned long long)computeBufferReferenceTypeSize(right->getType()), loc, true);
right = addBuiltInFunctionCall(loc, EOpConvPtrToUint64, true, right, TType(EbtUint64));
left = createConversion(EbtInt64, left);
left = addBinaryMath(EOpMul, left, size, loc);
TIntermTyped *node = addBinaryMath(op, left, right, loc);
node = addBuiltInFunctionCall(loc, EOpConvUint64ToPtr, true, node, referenceType);
return node;
}
if (op == EOpSub && left->isReference() && right->isReference()) {
TIntermConstantUnion* size =
addConstantUnion((long long)computeBufferReferenceTypeSize(left->getType()), loc, true);
left = addBuiltInFunctionCall(loc, EOpConvPtrToUint64, true, left, TType(EbtUint64));
right = addBuiltInFunctionCall(loc, EOpConvPtrToUint64, true, right, TType(EbtUint64));
left = addBuiltInFunctionCall(loc, EOpConvUint64ToInt64, true, left, TType(EbtInt64));
right = addBuiltInFunctionCall(loc, EOpConvUint64ToInt64, true, right, TType(EbtInt64));
left = addBinaryMath(EOpSub, left, right, loc);
TIntermTyped *node = addBinaryMath(EOpDiv, left, size, loc);
return node;
}
// No other math operators supported on references
if (left->isReference() || right->isReference())
return nullptr;
// Try converting the children's base types to compatible types.
auto children = addConversion(op, left, right);
left = std::get<0>(children);
@ -290,9 +291,7 @@ TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TInterm
// Convert "reference += int" to "reference = reference + int". We need this because the
// "reference + int" calculation involves a cast back to the original type, which makes it
// not an lvalue.
if ((op == EOpAddAssign || op == EOpSubAssign) && left->isReference() &&
extensionRequested(E_GL_EXT_buffer_reference2)) {
if ((op == EOpAddAssign || op == EOpSubAssign) && left->isReference()) {
if (!(right->getType().isScalar() && right->getType().isIntegerDomain()))
return nullptr;

View File

@ -751,8 +751,11 @@ TIntermTyped* TParseContext::handleBinaryMath(const TSourceLoc& loc, const char*
}
TIntermTyped* result = nullptr;
if (allowed)
if (allowed) {
if ((left->isReference() || right->isReference()))
requireExtensions(loc, 1, &E_GL_EXT_buffer_reference2, "buffer reference math");
result = intermediate.addBinaryMath(op, left, right, loc);
}
if (result == nullptr)
binaryOpError(loc, str, left->getCompleteString(), right->getCompleteString());
@ -1680,6 +1683,14 @@ TIntermTyped* TParseContext::addOutputArgumentConversions(const TFunction& funct
#endif
}
TIntermTyped* TParseContext::addAssign(const TSourceLoc& loc, TOperator op, TIntermTyped* left, TIntermTyped* right)
{
if ((op == EOpAddAssign || op == EOpSubAssign) && left->isReference())
requireExtensions(loc, 1, &E_GL_EXT_buffer_reference2, "+= and -= on a buffer reference");
return intermediate.addAssign(op, left, right, loc);
}
void TParseContext::memorySemanticsCheck(const TSourceLoc& loc, const TFunction& fnCandidate, const TIntermOperator& callNode)
{
const TIntermSequence* argp = &callNode.getAsAggregate()->getSequence();

View File

@ -328,6 +328,7 @@ public:
TIntermTyped* handleLengthMethod(const TSourceLoc&, TFunction*, TIntermNode*);
void addInputArgumentConversions(const TFunction&, TIntermNode*&) const;
TIntermTyped* addOutputArgumentConversions(const TFunction&, TIntermAggregate&) const;
TIntermTyped* addAssign(const TSourceLoc&, TOperator op, TIntermTyped* left, TIntermTyped* right);
void builtInOpCheck(const TSourceLoc&, const TFunction&, TIntermOperator&);
void nonOpBuiltInCheck(const TSourceLoc&, const TFunction&, TIntermAggregate&);
void userFunctionCallCheck(const TSourceLoc&, TIntermAggregate&);

View File

@ -778,7 +778,7 @@ assignment_expression
parseContext.specializationCheck($2.loc, $1->getType(), "=");
parseContext.lValueErrorCheck($2.loc, "assign", $1);
parseContext.rValueErrorCheck($2.loc, "assign", $3);
$$ = parseContext.intermediate.addAssign($2.op, $1, $3, $2.loc);
$$ = parseContext.addAssign($2.loc, $2.op, $1, $3);
if ($$ == 0) {
parseContext.assignError($2.loc, "assign", $1->getCompleteString(), $3->getCompleteString());
$$ = $1;

View File

@ -778,7 +778,7 @@ assignment_expression
parseContext.specializationCheck($2.loc, $1->getType(), "=");
parseContext.lValueErrorCheck($2.loc, "assign", $1);
parseContext.rValueErrorCheck($2.loc, "assign", $3);
$$ = parseContext.intermediate.addAssign($2.op, $1, $3, $2.loc);
$$ = parseContext.addAssign($2.loc, $2.op, $1, $3);
if ($$ == 0) {
parseContext.assignError($2.loc, "assign", $1->getCompleteString(), $3->getCompleteString());
$$ = $1;
@ -3885,4 +3885,3 @@ single_attribute
%%

File diff suppressed because it is too large Load Diff

View File

@ -30,8 +30,8 @@
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
#ifndef YY_YY_GLSLANG_TAB_CPP_H_INCLUDED
# define YY_YY_GLSLANG_TAB_CPP_H_INCLUDED
#ifndef YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED
# define YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED
/* Debug traces. */
#ifndef YYDEBUG
# define YYDEBUG 1
@ -470,7 +470,7 @@ extern int yydebug;
union YYSTYPE
{
#line 97 "glslang.y" /* yacc.c:1909 */
#line 97 "MachineIndependent/glslang.y" /* yacc.c:1909 */
struct {
glslang::TSourceLoc loc;
@ -506,7 +506,7 @@ union YYSTYPE
glslang::TArraySizes* typeParameters;
} interm;
#line 510 "glslang_tab.cpp.h" /* yacc.c:1909 */
#line 510 "MachineIndependent/glslang_tab.cpp.h" /* yacc.c:1909 */
};
typedef union YYSTYPE YYSTYPE;
@ -518,4 +518,4 @@ typedef union YYSTYPE YYSTYPE;
int yyparse (glslang::TParseContext* pParseContext);
#endif /* !YY_YY_GLSLANG_TAB_CPP_H_INCLUDED */
#endif /* !YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED */