Commit 4960baaf by John Kessenich

HLSL: Basic turn on of non-static member functions.

Still need: pass by reference in SPIR-V and symbol-table level for accessing 'this' members from member functions.
parent dfbdd9eb
......@@ -2747,7 +2747,8 @@ void TGlslangToSpvTraverser::makeFunctions(const glslang::TIntermSequence& glslF
const glslang::TType& paramType = parameters[p]->getAsTyped()->getType();
spv::Id typeId = convertGlslangToSpvType(paramType);
if (paramType.containsOpaque() ||
(paramType.getBasicType() == glslang::EbtBlock && paramType.getQualifier().storage == glslang::EvqBuffer))
(paramType.getBasicType() == glslang::EbtBlock &&
paramType.getQualifier().storage == glslang::EvqBuffer))
typeId = builder.makePointer(TranslateStorageClass(paramType), typeId);
else if (paramType.getQualifier().storage != glslang::EvqConstReadOnly)
typeId = builder.makePointer(spv::StorageClassFunction, typeId);
......
struct Test
{
float4 memVar;
float4 memFun(float4 a) : SV_Position
{
return 2 * a;
}
int memFun(int a) : SV_Position
{
return 2 + a;
}
int i;
};
float4 main() : SV_Target0
{
Test test;
float4 f4 = float4(1.0,1.0,1.0,1.0);
f4 += test.memFun(float4(5.0f,5.0f,5.0f,5.0f));
f4 += test.memFun(7);
return f4;
}
......@@ -2,5 +2,5 @@
// 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).
#define GLSLANG_REVISION "Overload400-PrecQual.1921"
#define GLSLANG_REVISION "Overload400-PrecQual.1922"
#define GLSLANG_DATE "19-Mar-2017"
......@@ -164,6 +164,7 @@ INSTANTIATE_TEST_CASE_P(
{"hlsl.multiEntry.vert", "RealEntrypoint"},
{"hlsl.multiReturn.frag", "main"},
{"hlsl.matrixindex.frag", "main"},
{"hlsl.nonstaticMemberFunction.frag", "main"},
{"hlsl.numericsuffixes.frag", "main"},
{"hlsl.numthreads.comp", "main_aux1"},
{"hlsl.overload.frag", "PixelShaderFunction"},
......
......@@ -1831,6 +1831,15 @@ bool HlslGrammar::acceptStruct(TType& type, TIntermNode*& nodeList)
parseContext.declareStruct(token.loc, structName, type);
// For member functions: now that we know the type of 'this', go back and
// - add their implicit argument with 'this' (not to the mangling, just the argument list)
// - parse the functions, their tokens were saved for deferred parsing (now)
for (int b = 0; b < (int)functionDeclarators.size(); ++b) {
// update signature
if (functionDeclarators[b].function->hasImplicitThis())
functionDeclarators[b].function->addThisParameter(type);
}
// All member functions get parsed inside the class/struct namespace and with the
// class/struct members in a symbol-table level.
parseContext.pushNamespace(structName);
......@@ -2059,6 +2068,8 @@ bool HlslGrammar::acceptMemberFunctionDefinition(TIntermNode*& nodeList, const T
TString* functionName = parseContext.getFullNamespaceName(memberName);
declarator.function = new TFunction(functionName, type);
if (type.getQualifier().storage == EvqTemporary)
declarator.function->setImplicitThis();
// function_parameters
if (acceptFunctionParameters(*declarator.function)) {
......@@ -2067,11 +2078,6 @@ bool HlslGrammar::acceptMemberFunctionDefinition(TIntermNode*& nodeList, const T
// compound_statement (function body definition)
if (peekTokenClass(EHTokLeftBrace)) {
if (declarator.function->getType().getQualifier().storage != EvqGlobal) {
expected("only static member functions are accepted");
return false;
}
declarator.loc = token.loc;
declarator.body = new TVector<HlslToken>;
accepted = acceptFunctionDefinition(declarator, nodeList, declarator.body);
......@@ -2221,7 +2227,7 @@ bool HlslGrammar::acceptFunctionDefinition(TFunctionDeclarator& declarator, TInt
if (deferredTokens)
return captureBlockTokens(*deferredTokens);
else
return acceptFunctionBody(declarator, nodeList);
return acceptFunctionBody(declarator, nodeList);
}
bool HlslGrammar::acceptFunctionBody(TFunctionDeclarator& declarator, TIntermNode*& nodeList)
......@@ -2609,7 +2615,7 @@ bool HlslGrammar::acceptPostfixExpression(TIntermTyped*& node)
HlslToken idToken;
// scopeBase will pick up the type symbol on the left of '::'
TSymbol* scopeBase = nullptr;
TSymbol* scope = nullptr;
// Find something before the postfix operations, as they can't operate
// on nothing. So, no "return true", they fall through, only "return false".
......@@ -2631,8 +2637,8 @@ bool HlslGrammar::acceptPostfixExpression(TIntermTyped*& node)
// user-type, identifier, or function name
if (peekTokenClass(EHTokColonColon)) {
TType type;
scopeBase = parseContext.lookupUserType(*idToken.string, type);
if (scopeBase == nullptr) {
scope = parseContext.lookupUserType(*idToken.string, type);
if (scope == nullptr) {
expected("type left of ::");
return false;
}
......@@ -2702,7 +2708,7 @@ bool HlslGrammar::acceptPostfixExpression(TIntermTyped*& node)
TIntermTyped* thisNode = node;
// arguments
if (! acceptFunctionCall(field, node, thisNode, scopeBase)) {
if (! acceptFunctionCall(field, node, thisNode, scope)) {
expected("function parameters");
return false;
}
......@@ -2775,16 +2781,21 @@ bool HlslGrammar::acceptConstructor(TIntermTyped*& node)
// : [idToken] arguments
//
bool HlslGrammar::acceptFunctionCall(HlslToken callToken, TIntermTyped*& node, TIntermTyped* baseObject,
const TSymbol* baseType)
const TSymbol* scope)
{
// name
TString* functionName = nullptr;
if ((baseObject == nullptr && baseType == nullptr)
|| parseContext.isBuiltInMethod(callToken.loc, baseObject, *callToken.string))
if ((baseObject == nullptr && scope == nullptr) ||
parseContext.isBuiltInMethod(callToken.loc, baseObject, *callToken.string)) {
// Built-in methods are not in the symbol table as methods, but as global functions
// taking an explicit 'this' as the first argument.
functionName = callToken.string;
else {
} else {
functionName = NewPoolTString("");
functionName->append(baseType->getType().getTypeName());
if (baseObject != nullptr)
functionName->append(baseObject->getType().getTypeName());
else if (scope != nullptr)
functionName->append(scope->getType().getTypeName());
parseContext.addScopeMangler(*functionName);
functionName->append(*callToken.string);
}
......
......@@ -105,7 +105,7 @@ namespace glslang {
bool acceptPostfixExpression(TIntermTyped*&);
bool acceptConstructor(TIntermTyped*&);
bool acceptFunctionCall(HlslToken, TIntermTyped*&, TIntermTyped* objectBase = nullptr,
const TSymbol* typeBase = nullptr);
const TSymbol* scope = nullptr);
bool acceptArguments(TFunction*, TIntermTyped*&);
bool acceptLiteral(TIntermTyped*&);
bool acceptCompoundStatement(TIntermNode*&);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment