Infrastructure: Move nesting counters, etc., to base class.

This lets all languages share the same definitions.
This commit is contained in:
John Kessenich 2017-06-06 19:19:45 -06:00
parent b4d46627cb
commit 9b2531ba23
6 changed files with 33 additions and 32 deletions

View File

@ -51,8 +51,8 @@ TParseContext::TParseContext(TSymbolTable& symbolTable, TIntermediate& interm, b
int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language,
TInfoSink& infoSink, bool forwardCompatible, EShMessages messages) :
TParseContextBase(symbolTable, interm, parsingBuiltins, version, profile, spvVersion, language, infoSink, forwardCompatible, messages),
contextPragma(true, false), loopNestingLevel(0), structNestingLevel(0), controlFlowNestingLevel(0), statementNestingLevel(0),
inMain(false), postMainReturn(false), currentFunctionType(nullptr), blockName(nullptr),
inMain(false),
blockName(nullptr),
limits(resources.limits),
atomicUintOffsets(nullptr), anyIndexLimits(false)
{
@ -912,7 +912,7 @@ TIntermAggregate* TParseContext::handleFunctionDefinition(const TSourceLoc& loc,
loopNestingLevel = 0;
statementNestingLevel = 0;
controlFlowNestingLevel = 0;
postMainReturn = false;
postEntryPointReturn = false;
return paramNodes;
}
@ -1193,7 +1193,7 @@ void TParseContext::checkLocation(const TSourceLoc& loc, TOperator op)
error(loc, "tessellation control barrier() cannot be placed within flow control", "", "");
if (! inMain)
error(loc, "tessellation control barrier() must be in main()", "", "");
else if (postMainReturn)
else if (postEntryPointReturn)
error(loc, "tessellation control barrier() cannot be placed after a return from main()", "", "");
}
break;

View File

@ -77,6 +77,10 @@ public:
TInfoSink& infoSink, bool forwardCompatible, EShMessages messages)
: TParseVersions(interm, version, profile, spvVersion, language, infoSink, forwardCompatible, messages),
symbolTable(symbolTable),
statementNestingLevel(0), loopNestingLevel(0), structNestingLevel(0), controlFlowNestingLevel(0),
postEntryPointReturn(false),
contextPragma(true, false),
limits(resources.limits),
parsingBuiltins(parsingBuiltins), scanContext(nullptr), ppContext(nullptr),
globalUniformBlock(nullptr)
{ }
@ -133,8 +137,6 @@ public:
extensionCallback(line, extension, behavior);
}
TSymbolTable& symbolTable; // symbol table that goes with the current language, version, and profile
// Manage the global uniform block (default uniforms in GLSL, $Global in HLSL)
virtual void growGlobalUniformBlock(const TSourceLoc&, TType&, const TString& memberName, TTypeList* typeList = nullptr);
@ -143,6 +145,23 @@ public:
const char* const scopeMangler = "::";
// Basic parsing state, easily accessible to the grammar
TSymbolTable& symbolTable; // symbol table that goes with the current language, version, and profile
int statementNestingLevel; // 0 if outside all flow control or compound statements
int loopNestingLevel; // 0 if outside all loops
int structNestingLevel; // 0 if outside blocks and structures
int controlFlowNestingLevel; // 0 if outside all flow control
const TType* currentFunctionType; // the return type of the function that's currently being parsed
bool functionReturnsValue; // true if a non-void function has a return
// if inside a function, true if the function is the entry point and this is after a return statement
bool postEntryPointReturn;
// case, node, case, case, node, ...; ensure only one node between cases; stack of them for nesting
TList<TIntermSequence*> switchSequenceStack;
// the statementNestingLevel the current switch statement is at, which must match the level of its case statements
TList<int> switchLevel;
struct TPragma contextPragma;
protected:
TParseContextBase(TParseContextBase&);
TParseContextBase& operator=(TParseContextBase&);
@ -151,6 +170,8 @@ protected:
TVector<TSymbol*> linkageSymbols; // these need to be transferred to 'linkage', after all editing is done
TScanContext* scanContext;
TPpContext* ppContext;
TBuiltInResource resources;
TLimits& limits;
// These, if set, will be called when a line, pragma ... is preprocessed.
// They will be called with any parameters to the original directive.
@ -384,17 +405,7 @@ public:
//
// Current state of parsing
struct TPragma contextPragma;
int loopNestingLevel; // 0 if outside all loops
int structNestingLevel; // 0 if outside blocks and structures
int controlFlowNestingLevel; // 0 if outside all flow control
int statementNestingLevel; // 0 if outside all flow control or compound statements
TList<TIntermSequence*> switchSequenceStack; // case, node, case, case, node, ...; ensure only one node between cases; stack of them for nesting
TList<int> switchLevel; // the statementNestingLevel the current switch statement is at, which must match the level of its case statements
bool inMain; // if inside a function, true if the function is main
bool postMainReturn; // if inside a function, true if the function is main and this is after a return statement
const TType* currentFunctionType; // the return type of the function that's currently being parsed
bool functionReturnsValue; // true if a non-void function has a return
const TString* blockName;
TQualifier currentBlockQualifier;
TPrecisionQualifier defaultPrecision[EbtNumTypes];

View File

@ -2777,7 +2777,7 @@ jump_statement
if (parseContext.currentFunctionType->getBasicType() != EbtVoid)
parseContext.error($1.loc, "non-void function must return a value", "return", "");
if (parseContext.inMain)
parseContext.postMainReturn = true;
parseContext.postEntryPointReturn = true;
}
| RETURN expression SEMICOLON {
$$ = parseContext.handleReturnValue($1.loc, $2);

View File

@ -7704,7 +7704,7 @@ yyreduce:
if (parseContext.currentFunctionType->getBasicType() != EbtVoid)
parseContext.error((yyvsp[-1].lex).loc, "non-void function must return a value", "return", "");
if (parseContext.inMain)
parseContext.postMainReturn = true;
parseContext.postEntryPointReturn = true;
}
#line 7710 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */
break;

View File

@ -57,10 +57,7 @@ HlslParseContext::HlslParseContext(TSymbolTable& symbolTable, TIntermediate& int
const TString sourceEntryPointName,
bool forwardCompatible, EShMessages messages) :
TParseContextBase(symbolTable, interm, parsingBuiltins, version, profile, spvVersion, language, infoSink, forwardCompatible, messages),
contextPragma(true, false),
loopNestingLevel(0), annotationNestingLevel(0), structNestingLevel(0), controlFlowNestingLevel(0),
postEntryPointReturn(false),
limits(resources.limits),
annotationNestingLevel(0),
inputPatch(nullptr),
builtInIoIndex(nullptr),
builtInIoBase(nullptr),
@ -520,6 +517,9 @@ TIntermTyped* HlslParseContext::handleSamplerLvalue(const TSourceLoc& loc, const
return node;
}
if (controlFlowNestingLevel > 0)
error(loc, "can't alias sampler in control flow", op, "");
// Best is if we are aliasing a flattened struct member "S.s1 = s2",
// in which case we want to update the flattening information with the alias,
// making everything else work seamlessly.

View File

@ -314,17 +314,7 @@ protected:
TIntermSymbol* findLinkageSymbol(TBuiltInVariable biType) const;
// Current state of parsing
struct TPragma contextPragma;
int loopNestingLevel; // 0 if outside all loops
int annotationNestingLevel; // 0 if outside all annotations
int structNestingLevel; // 0 if outside blocks and structures
int controlFlowNestingLevel; // 0 if outside all flow control
TList<TIntermSequence*> switchSequenceStack; // case, node, case, case, node, ...; ensure only one node between cases; stack of them for nesting
bool postEntryPointReturn; // if inside a function, true if the function is the entry point and this is after a return statement
const TType* currentFunctionType; // the return type of the function that's currently being parsed
bool functionReturnsValue; // true if a non-void function has a return
TBuiltInResource resources;
TLimits& limits;
HlslParseContext(HlslParseContext&);
HlslParseContext& operator=(HlslParseContext&);