HLSL: Non-functional: Drive existing method recognition by syntax, not by name.
This (and previous commit) is a better foundation to build real methods on.
This commit is contained in:
parent
78388726eb
commit
516d92d3c5
@ -2,5 +2,5 @@
|
|||||||
// For the version, it uses the latest git tag followed by the number of commits.
|
// For the version, it uses the latest git tag followed by the number of commits.
|
||||||
// For the date, it uses the current date (when then script is run).
|
// For the date, it uses the current date (when then script is run).
|
||||||
|
|
||||||
#define GLSLANG_REVISION "Overload400-PrecQual.1885"
|
#define GLSLANG_REVISION "Overload400-PrecQual.1886"
|
||||||
#define GLSLANG_DATE "08-Mar-2017"
|
#define GLSLANG_DATE "08-Mar-2017"
|
||||||
|
@ -2489,6 +2489,7 @@ bool HlslGrammar::acceptUnaryExpression(TIntermTyped*& node)
|
|||||||
// | function_call
|
// | function_call
|
||||||
// | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET
|
// | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET
|
||||||
// | postfix_expression DOT IDENTIFIER
|
// | postfix_expression DOT IDENTIFIER
|
||||||
|
// | postfix_expression DOT IDENTIFIER arguments
|
||||||
// | postfix_expression INC_OP
|
// | postfix_expression INC_OP
|
||||||
// | postfix_expression DEC_OP
|
// | postfix_expression DEC_OP
|
||||||
//
|
//
|
||||||
@ -2570,23 +2571,29 @@ bool HlslGrammar::acceptPostfixExpression(TIntermTyped*& node)
|
|||||||
case EOpIndexDirectStruct:
|
case EOpIndexDirectStruct:
|
||||||
{
|
{
|
||||||
// DOT IDENTIFIER
|
// DOT IDENTIFIER
|
||||||
// includes swizzles and struct members
|
// includes swizzles, member variables, and member functions
|
||||||
HlslToken field;
|
HlslToken field;
|
||||||
if (! acceptIdentifier(field)) {
|
if (! acceptIdentifier(field)) {
|
||||||
expected("swizzle or member");
|
expected("swizzle or member");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
TIntermTyped* base = node; // preserve for method function calls
|
if (peekTokenClass(EHTokLeftParen)) {
|
||||||
node = parseContext.handleDotDereference(field.loc, node, *field.string);
|
// member function
|
||||||
|
TIntermTyped* thisNode = node;
|
||||||
|
node = parseContext.handleBuiltInMethod(field.loc, node, *field.string);
|
||||||
|
if (node == nullptr) {
|
||||||
|
expected("built-in method");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// In the event of a method node, we look for an open paren and accept the function call.
|
// arguments
|
||||||
if (node != nullptr && node->getAsMethodNode() != nullptr && peekTokenClass(EHTokLeftParen)) {
|
if (! acceptFunctionCall(field, node, thisNode)) {
|
||||||
if (! acceptFunctionCall(field, node, base)) {
|
|
||||||
expected("function parameters");
|
expected("function parameters");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
} else
|
||||||
|
node = parseContext.handleDotDereference(field.loc, node, *field.string);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -862,47 +862,18 @@ bool HlslParseContext::isStructBufferMethod(const TString& name) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Handle seeing a base.field dereference in the grammar.
|
// Handle seeing a base.field dereference in the grammar, where 'field' is a
|
||||||
|
// swizzle or member variable.
|
||||||
//
|
//
|
||||||
TIntermTyped* HlslParseContext::handleDotDereference(const TSourceLoc& loc, TIntermTyped* base, const TString& field)
|
TIntermTyped* HlslParseContext::handleDotDereference(const TSourceLoc& loc, TIntermTyped* base, const TString& field)
|
||||||
{
|
{
|
||||||
variableCheck(base);
|
variableCheck(base);
|
||||||
|
|
||||||
//
|
|
||||||
// methods can't be resolved until we later see the function-calling syntax.
|
|
||||||
// Save away the name in the AST for now. Processing is completed in
|
|
||||||
// handleLengthMethod(), etc.
|
|
||||||
//
|
|
||||||
if (field == "length") {
|
|
||||||
return intermediate.addMethod(base, TType(EbtInt), &field, loc);
|
|
||||||
} else if (isSamplerMethod(field) && base->getType().getBasicType() == EbtSampler) {
|
|
||||||
// If it's not a method on a sampler object, we fall through to let other objects have a go.
|
|
||||||
const TSampler& sampler = base->getType().getSampler();
|
|
||||||
if (! sampler.isPureSampler()) {
|
|
||||||
const int vecSize = sampler.isShadow() ? 1 : 4; // TODO: handle arbitrary sample return sizes
|
|
||||||
return intermediate.addMethod(base, TType(sampler.type, EvqTemporary, vecSize), &field, loc);
|
|
||||||
}
|
|
||||||
} else if (isStructBufferType(base->getType())) {
|
|
||||||
TType retType(base->getType(), 0);
|
|
||||||
return intermediate.addMethod(base, retType, &field, loc);
|
|
||||||
} else if (field == "Append" ||
|
|
||||||
field == "RestartStrip") {
|
|
||||||
// We cannot check the type here: it may be sanitized if we're not compiling a geometry shader, but
|
|
||||||
// the code is around in the shader source.
|
|
||||||
return intermediate.addMethod(base, TType(EbtVoid), &field, loc);
|
|
||||||
}
|
|
||||||
|
|
||||||
// It's not .length() if we get to here.
|
|
||||||
|
|
||||||
if (base->isArray()) {
|
if (base->isArray()) {
|
||||||
error(loc, "cannot apply to an array:", ".", field.c_str());
|
error(loc, "cannot apply to an array:", ".", field.c_str());
|
||||||
|
|
||||||
return base;
|
return base;
|
||||||
}
|
}
|
||||||
|
|
||||||
// It's neither an array nor .length() if we get here,
|
|
||||||
// leaving swizzles and struct/block dereferences.
|
|
||||||
|
|
||||||
TIntermTyped* result = base;
|
TIntermTyped* result = base;
|
||||||
if (base->isVector() || base->isScalar()) {
|
if (base->isVector() || base->isScalar()) {
|
||||||
TSwizzleSelectors<TVectorSelector> selectors;
|
TSwizzleSelectors<TVectorSelector> selectors;
|
||||||
@ -1011,6 +982,43 @@ TIntermTyped* HlslParseContext::handleDotDereference(const TSourceLoc& loc, TInt
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Handle seeing a base.field dereference in the grammar, where 'field' is a
|
||||||
|
// built-in method.
|
||||||
|
//
|
||||||
|
// Return nullptr if 'field' is not a built-in method.
|
||||||
|
//
|
||||||
|
TIntermTyped* HlslParseContext::handleBuiltInMethod(const TSourceLoc& loc, TIntermTyped* base, const TString& field)
|
||||||
|
{
|
||||||
|
variableCheck(base);
|
||||||
|
|
||||||
|
//
|
||||||
|
// methods can't be resolved until we later see the function-calling syntax.
|
||||||
|
// Save away the name in the AST for now. Processing is completed in
|
||||||
|
// handleLengthMethod(), etc.
|
||||||
|
//
|
||||||
|
if (field == "length") {
|
||||||
|
return intermediate.addMethod(base, TType(EbtInt), &field, loc);
|
||||||
|
} else if (isSamplerMethod(field) && base->getType().getBasicType() == EbtSampler) {
|
||||||
|
// If it's not a method on a sampler object, we fall through to let other objects have a go.
|
||||||
|
const TSampler& sampler = base->getType().getSampler();
|
||||||
|
if (! sampler.isPureSampler()) {
|
||||||
|
const int vecSize = sampler.isShadow() ? 1 : 4; // TODO: handle arbitrary sample return sizes
|
||||||
|
return intermediate.addMethod(base, TType(sampler.type, EvqTemporary, vecSize), &field, loc);
|
||||||
|
}
|
||||||
|
} else if (isStructBufferType(base->getType())) {
|
||||||
|
TType retType(base->getType(), 0);
|
||||||
|
return intermediate.addMethod(base, retType, &field, loc);
|
||||||
|
} else if (field == "Append" ||
|
||||||
|
field == "RestartStrip") {
|
||||||
|
// We cannot check the type here: it may be sanitized if we're not compiling a geometry shader, but
|
||||||
|
// the code is around in the shader source.
|
||||||
|
return intermediate.addMethod(base, TType(EbtVoid), &field, loc);
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
// Split the type of the given node into two structs:
|
// Split the type of the given node into two structs:
|
||||||
// 1. interstage IO
|
// 1. interstage IO
|
||||||
// 2. everything else
|
// 2. everything else
|
||||||
|
@ -70,6 +70,7 @@ public:
|
|||||||
TIntermTyped* handleBinaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* left, TIntermTyped* right);
|
TIntermTyped* handleBinaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* left, TIntermTyped* right);
|
||||||
TIntermTyped* handleUnaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* childNode);
|
TIntermTyped* handleUnaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* childNode);
|
||||||
TIntermTyped* handleDotDereference(const TSourceLoc&, TIntermTyped* base, const TString& field);
|
TIntermTyped* handleDotDereference(const TSourceLoc&, TIntermTyped* base, const TString& field);
|
||||||
|
TIntermTyped* handleBuiltInMethod(const TSourceLoc&, TIntermTyped* base, const TString& field);
|
||||||
void assignLocations(TVariable& variable);
|
void assignLocations(TVariable& variable);
|
||||||
TFunction& handleFunctionDeclarator(const TSourceLoc&, TFunction& function, bool prototype);
|
TFunction& handleFunctionDeclarator(const TSourceLoc&, TFunction& function, bool prototype);
|
||||||
TIntermAggregate* handleFunctionDefinition(const TSourceLoc&, TFunction&, const TAttributeMap&, TIntermNode*& entryPointTree);
|
TIntermAggregate* handleFunctionDefinition(const TSourceLoc&, TFunction&, const TAttributeMap&, TIntermNode*& entryPointTree);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user