Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
A
angle
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Chen Yisong
angle
Commits
a5efff99
Commit
a5efff99
authored
Jun 06, 2013
by
Jamie Madill
Committed by
Shannon Woods
Jul 19, 2013
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Redesign layout qualifier parsing to be simpler and more storage efficient.
TRAC #23268 Signed-off-by: Geoff Lang Signed-off-by: Nicolas Capens Authored-by: Jamie Madill
parent
60ed9810
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
196 additions
and
90 deletions
+196
-90
BaseTypes.h
src/compiler/BaseTypes.h
+49
-13
ParseHelper.cpp
src/compiler/ParseHelper.cpp
+90
-24
ParseHelper.h
src/compiler/ParseHelper.h
+6
-4
SymbolTable.cpp
src/compiler/SymbolTable.cpp
+1
-1
Types.h
src/compiler/Types.h
+8
-4
glslang.y
src/compiler/glslang.y
+9
-10
glslang_tab.cpp
src/compiler/glslang_tab.cpp
+32
-32
glslang_tab.h
src/compiler/glslang_tab.h
+1
-2
No files found.
src/compiler/BaseTypes.h
View file @
a5efff99
...
@@ -133,25 +133,38 @@ enum TQualifier
...
@@ -133,25 +133,38 @@ enum TQualifier
EvqLast
EvqLast
};
};
// Layout qualifiers
enum
TLayoutMatrixPacking
enum
TLayoutQualifierType
{
{
ElqLocation
,
EmpUnspecified
,
ElqShared
,
EmpRowMajor
,
ElqPacked
,
EmpColumnMajor
ElqStd140
,
ElqRowMajor
,
ElqColumnMajor
,
ElqError
};
};
struct
TLayoutQualifierId
enum
TLayoutBlockStorage
{
{
TLayoutQualifierType
type
;
EbsUnspecified
,
int
location
;
EbsShared
,
EbsPacked
,
EbsStd140
};
};
typedef
std
::
vector
<
TLayoutQualifierId
>
TLayoutQualifier
;
struct
TLayoutQualifier
{
int
location
;
TLayoutMatrixPacking
matrixPacking
;
TLayoutBlockStorage
blockStorage
;
static
TLayoutQualifier
create
()
{
TLayoutQualifier
layoutQualifier
;
layoutQualifier
.
location
=
-
1
;
layoutQualifier
.
matrixPacking
=
EmpUnspecified
;
layoutQualifier
.
blockStorage
=
EbsUnspecified
;
return
layoutQualifier
;
}
};
//
//
// This is just for debug print out, carried along with the definitions above.
// This is just for debug print out, carried along with the definitions above.
...
@@ -193,6 +206,29 @@ inline const char* getQualifierString(TQualifier q)
...
@@ -193,6 +206,29 @@ inline const char* getQualifierString(TQualifier q)
}
}
}
}
inline
const
char
*
getMatrixPackingString
(
TLayoutMatrixPacking
mpq
)
{
switch
(
mpq
)
{
case
EmpUnspecified
:
return
"mp_unspecified"
;
case
EmpRowMajor
:
return
"row_major"
;
case
EmpColumnMajor
:
return
"column_major"
;
default:
return
"unknown matrix packing"
;
}
}
inline
const
char
*
getBlockStorageString
(
TLayoutBlockStorage
bsq
)
{
switch
(
bsq
)
{
case
EbsUnspecified
:
return
"bs_unspecified"
;
case
EbsShared
:
return
"shared"
;
case
EbsPacked
:
return
"packed"
;
case
EbsStd140
:
return
"std140"
;
default:
return
"unknown block storage"
;
}
}
inline
const
char
*
getInterpolationString
(
TQualifier
q
)
inline
const
char
*
getInterpolationString
(
TQualifier
q
)
{
{
switch
(
q
)
switch
(
q
)
...
...
src/compiler/ParseHelper.cpp
View file @
a5efff99
...
@@ -965,6 +965,45 @@ bool TParseContext::extensionErrorCheck(int line, const TString& extension)
...
@@ -965,6 +965,45 @@ bool TParseContext::extensionErrorCheck(int line, const TString& extension)
return
false
;
return
false
;
}
}
bool
TParseContext
::
singleDeclarationErrorCheck
(
TPublicType
&
publicType
,
TSourceLoc
identifierLocation
,
const
TString
&
identifier
)
{
if
(
structQualifierErrorCheck
(
identifierLocation
,
publicType
))
return
true
;
// check for layout qualifier issues
const
TLayoutQualifier
layoutQualifier
=
publicType
.
layoutQualifier
;
if
(
layoutQualifier
.
matrixPacking
!=
EmpUnspecified
)
{
error
(
identifierLocation
,
"layout qualifier"
,
getMatrixPackingString
(
layoutQualifier
.
matrixPacking
),
"only valid for interface blocks"
);
return
false
;
}
if
(
layoutQualifier
.
blockStorage
!=
EbsUnspecified
)
{
error
(
identifierLocation
,
"layout qualifier"
,
getBlockStorageString
(
layoutQualifier
.
blockStorage
),
"only valid for interface blocks"
);
return
false
;
}
if
(
publicType
.
qualifier
!=
EvqVertexInput
&&
publicType
.
qualifier
!=
EvqFragmentOutput
&&
layoutLocationErrorCheck
(
identifierLocation
,
publicType
.
layoutQualifier
))
{
return
false
;
}
return
false
;
}
bool
TParseContext
::
layoutLocationErrorCheck
(
TSourceLoc
location
,
const
TLayoutQualifier
&
layoutQualifier
)
{
if
(
layoutQualifier
.
location
!=
-
1
)
{
error
(
location
,
"invalid layout qualifier:"
,
"location"
,
"only valid on program inputs and outputs"
);
return
true
;
}
return
false
;
}
bool
TParseContext
::
supportsExtension
(
const
char
*
extension
)
bool
TParseContext
::
supportsExtension
(
const
char
*
extension
)
{
{
const
TExtensionBehavior
&
extbehavior
=
extensionBehavior
();
const
TExtensionBehavior
&
extbehavior
=
extensionBehavior
();
...
@@ -1130,10 +1169,11 @@ bool TParseContext::areAllChildConst(TIntermAggregate* aggrNode)
...
@@ -1130,10 +1169,11 @@ bool TParseContext::areAllChildConst(TIntermAggregate* aggrNode)
return
allConstant
;
return
allConstant
;
}
}
TPublicType
TParseContext
::
addFullySpecifiedType
(
TQualifier
qualifier
,
const
TPublicType
&
typeSpecifier
)
TPublicType
TParseContext
::
addFullySpecifiedType
(
TQualifier
qualifier
,
TLayoutQualifier
layoutQualifier
,
const
TPublicType
&
typeSpecifier
)
{
{
TPublicType
returnType
=
typeSpecifier
;
TPublicType
returnType
=
typeSpecifier
;
returnType
.
qualifier
=
qualifier
;
returnType
.
qualifier
=
qualifier
;
returnType
.
layoutQualifier
=
layoutQualifier
;
if
(
typeSpecifier
.
array
)
if
(
typeSpecifier
.
array
)
{
{
...
@@ -1250,7 +1290,7 @@ TIntermAggregate* TParseContext::parseSingleArrayDeclaration(TPublicType &public
...
@@ -1250,7 +1290,7 @@ TIntermAggregate* TParseContext::parseSingleArrayDeclaration(TPublicType &public
TIntermAggregate
*
TParseContext
::
parseSingleInitDeclaration
(
TPublicType
&
publicType
,
TSourceLoc
identifierLocation
,
const
TString
&
identifier
,
TSourceLoc
initLocation
,
TIntermTyped
*
initializer
)
TIntermAggregate
*
TParseContext
::
parseSingleInitDeclaration
(
TPublicType
&
publicType
,
TSourceLoc
identifierLocation
,
const
TString
&
identifier
,
TSourceLoc
initLocation
,
TIntermTyped
*
initializer
)
{
{
if
(
s
tructQualifierErrorCheck
(
identifierLocation
,
publicType
))
if
(
s
ingleDeclarationErrorCheck
(
publicType
,
identifierLocation
,
identifier
))
recover
();
recover
();
TIntermNode
*
intermNode
;
TIntermNode
*
intermNode
;
...
@@ -1719,6 +1759,12 @@ TIntermAggregate* TParseContext::addInterfaceBlock(const TPublicType& typeQualif
...
@@ -1719,6 +1759,12 @@ TIntermAggregate* TParseContext::addInterfaceBlock(const TPublicType& typeQualif
recover
();
recover
();
}
}
const
TLayoutQualifier
layoutQualifier
=
typeQualifier
.
layoutQualifier
;
if
(
layoutLocationErrorCheck
(
typeQualifier
.
line
,
layoutQualifier
))
{
recover
();
}
TSymbol
*
blockNameSymbol
=
new
TInterfaceBlockName
(
&
blockName
);
TSymbol
*
blockNameSymbol
=
new
TInterfaceBlockName
(
&
blockName
);
if
(
!
symbolTable
.
declare
(
*
blockNameSymbol
))
{
if
(
!
symbolTable
.
declare
(
*
blockNameSymbol
))
{
error
(
nameLine
,
"redefinition"
,
blockName
.
c_str
(),
"interface block name"
);
error
(
nameLine
,
"redefinition"
,
blockName
.
c_str
(),
"interface block name"
);
...
@@ -1745,11 +1791,18 @@ TIntermAggregate* TParseContext::addInterfaceBlock(const TPublicType& typeQualif
...
@@ -1745,11 +1791,18 @@ TIntermAggregate* TParseContext::addInterfaceBlock(const TPublicType& typeQualif
recover
();
recover
();
break
;
break
;
}
}
// check layout qualifiers
if
(
layoutLocationErrorCheck
(
memberTypeLine
.
line
,
memberType
->
getLayoutQualifier
()))
{
recover
();
}
}
}
TType
*
interfaceBlock
=
new
TType
(
typeList
,
blockName
);
TType
*
interfaceBlock
=
new
TType
(
typeList
,
blockName
);
interfaceBlock
->
setBasicType
(
EbtInterfaceBlock
);
interfaceBlock
->
setBasicType
(
EbtInterfaceBlock
);
interfaceBlock
->
setQualifier
(
typeQualifier
.
qualifier
);
interfaceBlock
->
setQualifier
(
typeQualifier
.
qualifier
);
interfaceBlock
->
setLayoutQualifier
(
layoutQualifier
);
TString
symbolName
=
""
;
TString
symbolName
=
""
;
int
symbolId
=
0
;
int
symbolId
=
0
;
...
@@ -2182,32 +2235,33 @@ TIntermTyped* TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpre
...
@@ -2182,32 +2235,33 @@ TIntermTyped* TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpre
return
indexedExpression
;
return
indexedExpression
;
}
}
TLayoutQualifier
Id
TParseContext
::
addLayoutQualifierId
(
const
TString
&
qualifierType
,
TSourceLoc
qualifierTypeLine
)
TLayoutQualifier
TParseContext
::
parseLayoutQualifier
(
const
TString
&
qualifierType
,
TSourceLoc
qualifierTypeLine
)
{
{
TLayoutQualifier
Id
qualifierId
;
TLayoutQualifier
qualifier
;
qualifierId
.
type
=
ElqError
;
qualifier
.
location
=
-
1
;
qualifierId
.
location
=
-
1
;
qualifier
.
matrixPacking
=
EmpUnspecified
;
qualifier
.
blockStorage
=
EbsUnspecified
;
if
(
qualifierType
==
"shared"
)
if
(
qualifierType
==
"shared"
)
{
{
qualifier
Id
.
type
=
Elq
Shared
;
qualifier
.
blockStorage
=
Ebs
Shared
;
}
}
else
if
(
qualifierType
==
"packed"
)
else
if
(
qualifierType
==
"packed"
)
{
{
qualifier
Id
.
type
=
Elq
Packed
;
qualifier
.
blockStorage
=
Ebs
Packed
;
}
}
else
if
(
qualifierType
==
"std140"
)
else
if
(
qualifierType
==
"std140"
)
{
{
qualifier
Id
.
type
=
Elq
Std140
;
qualifier
.
blockStorage
=
Ebs
Std140
;
}
}
else
if
(
qualifierType
==
"row_major"
)
else
if
(
qualifierType
==
"row_major"
)
{
{
qualifier
Id
.
type
=
Elq
RowMajor
;
qualifier
.
matrixPacking
=
Emp
RowMajor
;
}
}
else
if
(
qualifierType
==
"column_major"
)
else
if
(
qualifierType
==
"column_major"
)
{
{
qualifier
Id
.
type
=
Elq
ColumnMajor
;
qualifier
.
matrixPacking
=
Emp
ColumnMajor
;
}
}
else
if
(
qualifierType
==
"location"
)
else
if
(
qualifierType
==
"location"
)
{
{
...
@@ -2220,15 +2274,16 @@ TLayoutQualifierId TParseContext::addLayoutQualifierId(const TString &qualifierT
...
@@ -2220,15 +2274,16 @@ TLayoutQualifierId TParseContext::addLayoutQualifierId(const TString &qualifierT
recover
();
recover
();
}
}
return
qualifier
Id
;
return
qualifier
;
}
}
TLayoutQualifier
Id
TParseContext
::
addLayoutQualifierId
(
const
TString
&
qualifierType
,
TSourceLoc
qualifierTypeLine
,
const
TString
&
intValueString
,
int
intValue
,
TSourceLoc
intValueLine
)
TLayoutQualifier
TParseContext
::
parseLayoutQualifier
(
const
TString
&
qualifierType
,
TSourceLoc
qualifierTypeLine
,
const
TString
&
intValueString
,
int
intValue
,
TSourceLoc
intValueLine
)
{
{
TLayoutQualifier
Id
qualifierId
;
TLayoutQualifier
qualifier
;
qualifierId
.
type
=
ElqError
;
qualifier
.
location
=
-
1
;
qualifierId
.
location
=
-
1
;
qualifier
.
matrixPacking
=
EmpUnspecified
;
qualifier
.
blockStorage
=
EbsUnspecified
;
if
(
qualifierType
!=
"location"
)
if
(
qualifierType
!=
"location"
)
{
{
...
@@ -2244,23 +2299,33 @@ TLayoutQualifierId TParseContext::addLayoutQualifierId(const TString &qualifierT
...
@@ -2244,23 +2299,33 @@ TLayoutQualifierId TParseContext::addLayoutQualifierId(const TString &qualifierT
}
}
else
else
{
{
qualifier
Id
.
location
=
intValue
;
qualifier
.
location
=
intValue
;
}
}
// TODO: must check that location is < MAX_DRAW_BUFFERS
// TODO: must check that location is < MAX_DRAW_BUFFERS
}
}
return
qualifier
Id
;
return
qualifier
;
}
}
TLayoutQualifier
*
TParseContext
::
makeLayoutQualifierFromId
(
TLayoutQualifierId
layoutQualifierId
)
TLayoutQualifier
TParseContext
::
joinLayoutQualifiers
(
TLayoutQualifier
leftQualifier
,
TLayoutQualifier
rightQualifier
)
{
{
return
NULL
;
TLayoutQualifier
joinedQualifier
=
leftQualifier
;
}
TLayoutQualifier
*
TParseContext
::
extendLayoutQualifier
(
TLayoutQualifier
*
layoutQualifier
,
TLayoutQualifierId
layoutQualifierId
)
if
(
rightQualifier
.
location
!=
-
1
)
{
{
return
NULL
;
joinedQualifier
.
location
=
rightQualifier
.
location
;
}
if
(
rightQualifier
.
matrixPacking
!=
EmpUnspecified
)
{
joinedQualifier
.
matrixPacking
=
rightQualifier
.
matrixPacking
;
}
if
(
rightQualifier
.
blockStorage
!=
EbsUnspecified
)
{
joinedQualifier
.
blockStorage
=
rightQualifier
.
blockStorage
;
}
return
joinedQualifier
;
}
}
TTypeList
*
TParseContext
::
addStructDeclaratorList
(
const
TPublicType
&
typeSpecifier
,
TTypeList
*
typeList
)
TTypeList
*
TParseContext
::
addStructDeclaratorList
(
const
TPublicType
&
typeSpecifier
,
TTypeList
*
typeList
)
...
@@ -2279,6 +2344,7 @@ TTypeList *TParseContext::addStructDeclaratorList(const TPublicType& typeSpecifi
...
@@ -2279,6 +2344,7 @@ TTypeList *TParseContext::addStructDeclaratorList(const TPublicType& typeSpecifi
type
->
setSecondarySize
(
typeSpecifier
.
secondarySize
);
type
->
setSecondarySize
(
typeSpecifier
.
secondarySize
);
type
->
setPrecision
(
typeSpecifier
.
precision
);
type
->
setPrecision
(
typeSpecifier
.
precision
);
type
->
setQualifier
(
typeSpecifier
.
qualifier
);
type
->
setQualifier
(
typeSpecifier
.
qualifier
);
type
->
setLayoutQualifier
(
typeSpecifier
.
layoutQualifier
);
// don't allow arrays of arrays
// don't allow arrays of arrays
if
(
type
->
isArray
())
{
if
(
type
->
isArray
())
{
...
...
src/compiler/ParseHelper.h
View file @
a5efff99
...
@@ -100,6 +100,8 @@ struct TParseContext {
...
@@ -100,6 +100,8 @@ struct TParseContext {
bool
nonInitErrorCheck
(
int
line
,
const
TString
&
identifier
,
const
TPublicType
&
type
,
TVariable
*&
variable
);
bool
nonInitErrorCheck
(
int
line
,
const
TString
&
identifier
,
const
TPublicType
&
type
,
TVariable
*&
variable
);
bool
paramErrorCheck
(
int
line
,
TQualifier
qualifier
,
TQualifier
paramQualifier
,
TType
*
type
);
bool
paramErrorCheck
(
int
line
,
TQualifier
qualifier
,
TQualifier
paramQualifier
,
TType
*
type
);
bool
extensionErrorCheck
(
int
line
,
const
TString
&
);
bool
extensionErrorCheck
(
int
line
,
const
TString
&
);
bool
singleDeclarationErrorCheck
(
TPublicType
&
publicType
,
TSourceLoc
identifierLocation
,
const
TString
&
identifier
);
bool
layoutLocationErrorCheck
(
TSourceLoc
location
,
const
TLayoutQualifier
&
layoutQualifier
);
const
TExtensionBehavior
&
extensionBehavior
()
const
{
return
directiveHandler
.
extensionBehavior
();
}
const
TExtensionBehavior
&
extensionBehavior
()
const
{
return
directiveHandler
.
extensionBehavior
();
}
bool
supportsExtension
(
const
char
*
extension
);
bool
supportsExtension
(
const
char
*
extension
);
...
@@ -116,6 +118,7 @@ struct TParseContext {
...
@@ -116,6 +118,7 @@ struct TParseContext {
bool
arraySetMaxSize
(
TIntermSymbol
*
,
TType
*
,
int
,
bool
,
TSourceLoc
);
bool
arraySetMaxSize
(
TIntermSymbol
*
,
TType
*
,
int
,
bool
,
TSourceLoc
);
TPublicType
addFullySpecifiedType
(
TQualifier
qualifier
,
const
TPublicType
&
typeSpecifier
);
TPublicType
addFullySpecifiedType
(
TQualifier
qualifier
,
const
TPublicType
&
typeSpecifier
);
TPublicType
addFullySpecifiedType
(
TQualifier
qualifier
,
TLayoutQualifier
layoutQualifier
,
const
TPublicType
&
typeSpecifier
);
TIntermAggregate
*
parseSingleDeclaration
(
TPublicType
&
publicType
,
TSourceLoc
identifierLocation
,
const
TString
&
identifier
);
TIntermAggregate
*
parseSingleDeclaration
(
TPublicType
&
publicType
,
TSourceLoc
identifierLocation
,
const
TString
&
identifier
);
TIntermAggregate
*
parseSingleArrayDeclaration
(
TPublicType
&
publicType
,
TSourceLoc
identifierLocation
,
const
TString
&
identifier
,
TSourceLoc
indexLocation
,
TIntermTyped
*
indexExpression
);
TIntermAggregate
*
parseSingleArrayDeclaration
(
TPublicType
&
publicType
,
TSourceLoc
identifierLocation
,
const
TString
&
identifier
,
TSourceLoc
indexLocation
,
TIntermTyped
*
indexExpression
);
TIntermAggregate
*
parseSingleInitDeclaration
(
TPublicType
&
publicType
,
TSourceLoc
identifierLocation
,
const
TString
&
identifier
,
TSourceLoc
initLocation
,
TIntermTyped
*
initializer
);
TIntermAggregate
*
parseSingleInitDeclaration
(
TPublicType
&
publicType
,
TSourceLoc
identifierLocation
,
const
TString
&
identifier
,
TSourceLoc
initLocation
,
TIntermTyped
*
initializer
);
...
@@ -137,10 +140,9 @@ struct TParseContext {
...
@@ -137,10 +140,9 @@ struct TParseContext {
TIntermAggregate
*
addInterfaceBlock
(
const
TPublicType
&
typeQualifier
,
TSourceLoc
nameLine
,
const
TString
&
blockName
,
TTypeList
*
typeList
,
TIntermAggregate
*
addInterfaceBlock
(
const
TPublicType
&
typeQualifier
,
TSourceLoc
nameLine
,
const
TString
&
blockName
,
TTypeList
*
typeList
,
const
TString
&
instanceName
,
TSourceLoc
instanceLine
,
TIntermTyped
*
arrayIndex
,
TSourceLoc
arrayIndexLine
);
const
TString
&
instanceName
,
TSourceLoc
instanceLine
,
TIntermTyped
*
arrayIndex
,
TSourceLoc
arrayIndexLine
);
TLayoutQualifierId
addLayoutQualifierId
(
const
TString
&
qualifierType
,
TSourceLoc
qualifierTypeLine
);
TLayoutQualifier
parseLayoutQualifier
(
const
TString
&
qualifierType
,
TSourceLoc
qualifierTypeLine
);
TLayoutQualifierId
addLayoutQualifierId
(
const
TString
&
qualifierType
,
TSourceLoc
qualifierTypeLine
,
const
TString
&
intValueString
,
int
intValue
,
TSourceLoc
intValueLine
);
TLayoutQualifier
parseLayoutQualifier
(
const
TString
&
qualifierType
,
TSourceLoc
qualifierTypeLine
,
const
TString
&
intValueString
,
int
intValue
,
TSourceLoc
intValueLine
);
TLayoutQualifier
*
makeLayoutQualifierFromId
(
TLayoutQualifierId
layoutQualifierId
);
TLayoutQualifier
joinLayoutQualifiers
(
TLayoutQualifier
leftQualifier
,
TLayoutQualifier
rightQualifier
);
TLayoutQualifier
*
extendLayoutQualifier
(
TLayoutQualifier
*
layoutQualifier
,
TLayoutQualifierId
layoutQualifierId
);
// Performs an error check for embedded struct declarations.
// Performs an error check for embedded struct declarations.
// Returns true if an error was raised due to the declaration of
// Returns true if an error was raised due to the declaration of
...
...
src/compiler/SymbolTable.cpp
View file @
a5efff99
...
@@ -21,7 +21,7 @@
...
@@ -21,7 +21,7 @@
#include "common/angleutils.h"
#include "common/angleutils.h"
TType
::
TType
(
const
TPublicType
&
p
)
:
TType
::
TType
(
const
TPublicType
&
p
)
:
type
(
p
.
type
),
precision
(
p
.
precision
),
qualifier
(
p
.
qualifier
),
primarySize
(
p
.
primarySize
),
secondarySize
(
p
.
secondarySize
),
array
(
p
.
array
),
arraySize
(
p
.
arraySize
),
type
(
p
.
type
),
precision
(
p
.
precision
),
qualifier
(
p
.
qualifier
),
primarySize
(
p
.
primarySize
),
secondarySize
(
p
.
secondarySize
),
array
(
p
.
array
),
layoutQualifier
(
p
.
layoutQualifier
),
arraySize
(
p
.
arraySize
),
maxArraySize
(
0
),
arrayInformationType
(
0
),
interfaceBlockType
(
0
),
structure
(
0
),
structureSize
(
0
),
deepestStructNesting
(
0
),
fieldName
(
0
),
mangled
(
0
),
typeName
(
0
)
maxArraySize
(
0
),
arrayInformationType
(
0
),
interfaceBlockType
(
0
),
structure
(
0
),
structureSize
(
0
),
deepestStructNesting
(
0
),
fieldName
(
0
),
mangled
(
0
),
typeName
(
0
)
{
{
if
(
p
.
userDef
)
{
if
(
p
.
userDef
)
{
...
...
src/compiler/Types.h
View file @
a5efff99
...
@@ -38,13 +38,13 @@ public:
...
@@ -38,13 +38,13 @@ public:
POOL_ALLOCATOR_NEW_DELETE
(
GlobalPoolAllocator
)
POOL_ALLOCATOR_NEW_DELETE
(
GlobalPoolAllocator
)
TType
()
{}
TType
()
{}
TType
(
TBasicType
t
,
TPrecision
p
,
TQualifier
q
=
EvqTemporary
,
int
ps
=
1
,
int
ss
=
1
,
bool
a
=
false
)
:
TType
(
TBasicType
t
,
TPrecision
p
,
TQualifier
q
=
EvqTemporary
,
int
ps
=
1
,
int
ss
=
1
,
bool
a
=
false
)
:
type
(
t
),
precision
(
p
),
qualifier
(
q
),
primarySize
(
ps
),
secondarySize
(
ss
),
array
(
a
),
arraySize
(
0
),
type
(
t
),
precision
(
p
),
qualifier
(
q
),
primarySize
(
ps
),
secondarySize
(
ss
),
array
(
a
),
layoutQualifier
(
TLayoutQualifier
::
create
()),
arraySize
(
0
),
maxArraySize
(
0
),
arrayInformationType
(
0
),
interfaceBlockType
(
0
),
structure
(
0
),
structureSize
(
0
),
deepestStructNesting
(
0
),
fieldName
(
0
),
mangled
(
0
),
typeName
(
0
),
instanceName
(
0
)
maxArraySize
(
0
),
arrayInformationType
(
0
),
interfaceBlockType
(
0
),
structure
(
0
),
structureSize
(
0
),
deepestStructNesting
(
0
),
fieldName
(
0
),
mangled
(
0
),
typeName
(
0
),
instanceName
(
0
)
{
{
}
}
explicit
TType
(
const
TPublicType
&
p
);
explicit
TType
(
const
TPublicType
&
p
);
TType
(
TTypeList
*
userDef
,
const
TString
&
n
,
TPrecision
p
=
EbpUndefined
)
:
TType
(
TTypeList
*
userDef
,
const
TString
&
n
,
TPrecision
p
=
EbpUndefined
)
:
type
(
EbtStruct
),
precision
(
p
),
qualifier
(
EvqTemporary
),
primarySize
(
1
),
secondarySize
(
1
),
array
(
false
),
arraySize
(
0
),
type
(
EbtStruct
),
precision
(
p
),
qualifier
(
EvqTemporary
),
primarySize
(
1
),
secondarySize
(
1
),
array
(
false
),
layoutQualifier
(
TLayoutQualifier
::
create
()),
arraySize
(
0
),
maxArraySize
(
0
),
arrayInformationType
(
0
),
interfaceBlockType
(
0
),
structure
(
userDef
),
structureSize
(
0
),
deepestStructNesting
(
0
),
fieldName
(
0
),
mangled
(
0
),
instanceName
(
0
)
maxArraySize
(
0
),
arrayInformationType
(
0
),
interfaceBlockType
(
0
),
structure
(
userDef
),
structureSize
(
0
),
deepestStructNesting
(
0
),
fieldName
(
0
),
mangled
(
0
),
instanceName
(
0
)
{
{
typeName
=
NewPoolTString
(
n
.
c_str
());
typeName
=
NewPoolTString
(
n
.
c_str
());
...
@@ -59,6 +59,9 @@ public:
...
@@ -59,6 +59,9 @@ public:
TQualifier
getQualifier
()
const
{
return
qualifier
;
}
TQualifier
getQualifier
()
const
{
return
qualifier
;
}
void
setQualifier
(
TQualifier
q
)
{
qualifier
=
q
;
}
void
setQualifier
(
TQualifier
q
)
{
qualifier
=
q
;
}
TLayoutQualifier
getLayoutQualifier
()
const
{
return
layoutQualifier
;
}
void
setLayoutQualifier
(
TLayoutQualifier
lq
)
{
layoutQualifier
=
lq
;
}
int
getNominalSize
()
const
{
return
primarySize
;
}
int
getNominalSize
()
const
{
return
primarySize
;
}
int
getSecondarySize
()
const
{
return
secondarySize
;
}
int
getSecondarySize
()
const
{
return
secondarySize
;
}
int
getCols
()
const
{
ASSERT
(
isMatrix
());
return
primarySize
;
}
int
getCols
()
const
{
ASSERT
(
isMatrix
());
return
primarySize
;
}
...
@@ -247,6 +250,7 @@ protected:
...
@@ -247,6 +250,7 @@ protected:
TPrecision
precision
:
4
;
TPrecision
precision
:
4
;
TQualifier
qualifier
:
7
;
TQualifier
qualifier
:
7
;
unsigned
int
array
:
1
;
unsigned
int
array
:
1
;
TLayoutQualifier
layoutQualifier
;
int
primarySize
;
// size of vector or cols matrix
int
primarySize
;
// size of vector or cols matrix
int
secondarySize
;
// rows of a matrix
int
secondarySize
;
// rows of a matrix
int
arraySize
;
int
arraySize
;
...
@@ -276,7 +280,7 @@ protected:
...
@@ -276,7 +280,7 @@ protected:
struct
TPublicType
struct
TPublicType
{
{
TBasicType
type
;
TBasicType
type
;
TLayoutQualifier
*
layoutQualifier
;
TLayoutQualifier
layoutQualifier
;
TQualifier
qualifier
;
TQualifier
qualifier
;
TPrecision
precision
;
TPrecision
precision
;
int
primarySize
;
// size of vector or cols of matrix
int
primarySize
;
// size of vector or cols of matrix
...
@@ -289,7 +293,7 @@ struct TPublicType
...
@@ -289,7 +293,7 @@ struct TPublicType
void
setBasic
(
TBasicType
bt
,
TQualifier
q
,
int
ln
=
0
)
void
setBasic
(
TBasicType
bt
,
TQualifier
q
,
int
ln
=
0
)
{
{
type
=
bt
;
type
=
bt
;
layoutQualifier
=
NULL
;
layoutQualifier
=
TLayoutQualifier
::
create
()
;
qualifier
=
q
;
qualifier
=
q
;
precision
=
EbpUndefined
;
precision
=
EbpUndefined
;
primarySize
=
1
;
primarySize
=
1
;
...
...
src/compiler/glslang.y
View file @
a5efff99
...
@@ -72,8 +72,7 @@ WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h).
...
@@ -72,8 +72,7 @@ WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h).
union {
union {
TPublicType type;
TPublicType type;
TPrecision precision;
TPrecision precision;
TLayoutQualifierId layoutQualifierId;
TLayoutQualifier layoutQualifier;
TLayoutQualifier* layoutQualifier;
TQualifier qualifier;
TQualifier qualifier;
TFunction* function;
TFunction* function;
TParameter param;
TParameter param;
...
@@ -171,8 +170,7 @@ extern void yyerror(TParseContext* context, const char* reason);
...
@@ -171,8 +170,7 @@ extern void yyerror(TParseContext* context, const char* reason);
%type <interm> parameter_declaration parameter_declarator parameter_type_specifier
%type <interm> parameter_declaration parameter_declarator parameter_type_specifier
%type <interm.qualifier> parameter_qualifier parameter_type_qualifier
%type <interm.qualifier> parameter_qualifier parameter_type_qualifier
%type <interm.layoutQualifier> layout_qualifier layout_qualifier_id_list
%type <interm.layoutQualifier> layout_qualifier layout_qualifier_id_list layout_qualifier_id
%type <interm.layoutQualifierId> layout_qualifier_id
%type <interm.precision> precision_qualifier
%type <interm.precision> precision_qualifier
%type <interm.type> type_qualifier fully_specified_type type_specifier storage_qualifier interpolation_qualifier
%type <interm.type> type_qualifier fully_specified_type type_specifier storage_qualifier interpolation_qualifier
...
@@ -1220,7 +1218,7 @@ fully_specified_type
...
@@ -1220,7 +1218,7 @@ fully_specified_type
}
}
}
}
| type_qualifier type_specifier {
| type_qualifier type_specifier {
$$ = context->addFullySpecifiedType($1.qualifier, $2);
$$ = context->addFullySpecifiedType($1.qualifier, $
1.layoutQualifier, $
2);
}
}
;
;
...
@@ -1404,22 +1402,22 @@ layout_qualifier
...
@@ -1404,22 +1402,22 @@ layout_qualifier
layout_qualifier_id_list
layout_qualifier_id_list
: layout_qualifier_id {
: layout_qualifier_id {
$$ =
context->makeLayoutQualifierFromId($1)
;
$$ =
$1
;
}
}
| layout_qualifier_id_list COMMA layout_qualifier_id {
| layout_qualifier_id_list COMMA layout_qualifier_id {
$$ = context->
extendLayoutQualifier
($1, $3);
$$ = context->
joinLayoutQualifiers
($1, $3);
}
}
;
;
layout_qualifier_id
layout_qualifier_id
: IDENTIFIER {
: IDENTIFIER {
$$ = context->
addLayoutQualifierId
(*$1.string, $1.line);
$$ = context->
parseLayoutQualifier
(*$1.string, $1.line);
}
}
| IDENTIFIER EQUAL INTCONSTANT {
| IDENTIFIER EQUAL INTCONSTANT {
$$ = context->
addLayoutQualifierId
(*$1.string, $1.line, *$3.string, $3.i, $3.line);
$$ = context->
parseLayoutQualifier
(*$1.string, $1.line, *$3.string, $3.i, $3.line);
}
}
| IDENTIFIER EQUAL UINTCONSTANT {
| IDENTIFIER EQUAL UINTCONSTANT {
$$ = context->
addLayoutQualifierId
(*$1.string, $1.line, *$3.string, $3.i, $3.line);
$$ = context->
parseLayoutQualifier
(*$1.string, $1.line, *$3.string, $3.i, $3.line);
}
}
;
;
...
@@ -1649,6 +1647,7 @@ struct_declaration
...
@@ -1649,6 +1647,7 @@ struct_declaration
| type_qualifier type_specifier struct_declarator_list SEMICOLON {
| type_qualifier type_specifier struct_declarator_list SEMICOLON {
// ES3 Only, but errors should be handled elsewhere
// ES3 Only, but errors should be handled elsewhere
$2.qualifier = $1.qualifier;
$2.qualifier = $1.qualifier;
$2.layoutQualifier = $1.layoutQualifier;
$$ = context->addStructDeclaratorList($2, $3);
$$ = context->addStructDeclaratorList($2, $3);
}
}
;
;
...
...
src/compiler/glslang_tab.cpp
View file @
a5efff99
...
@@ -276,8 +276,7 @@ typedef union YYSTYPE
...
@@ -276,8 +276,7 @@ typedef union YYSTYPE
union
{
union
{
TPublicType
type
;
TPublicType
type
;
TPrecision
precision
;
TPrecision
precision
;
TLayoutQualifierId
layoutQualifierId
;
TLayoutQualifier
layoutQualifier
;
TLayoutQualifier
*
layoutQualifier
;
TQualifier
qualifier
;
TQualifier
qualifier
;
TFunction
*
function
;
TFunction
*
function
;
TParameter
param
;
TParameter
param
;
...
@@ -741,30 +740,30 @@ static const yytype_int16 yyrhs[] =
...
@@ -741,30 +740,30 @@ static const yytype_int16 yyrhs[] =
/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
static
const
yytype_uint16
yyrline
[]
=
static
const
yytype_uint16
yyrline
[]
=
{
{
0
,
19
4
,
194
,
195
,
198
,
233
,
236
,
241
,
246
,
251
,
0
,
19
2
,
192
,
193
,
196
,
231
,
234
,
239
,
244
,
249
,
25
6
,
262
,
265
,
268
,
271
,
274
,
284
,
297
,
305
,
405
,
25
4
,
260
,
263
,
266
,
269
,
272
,
282
,
295
,
303
,
403
,
40
8
,
416
,
420
,
427
,
431
,
438
,
444
,
453
,
461
,
464
,
40
6
,
414
,
418
,
425
,
429
,
436
,
442
,
451
,
459
,
462
,
47
4
,
477
,
487
,
497
,
518
,
519
,
520
,
525
,
526
,
535
,
47
2
,
475
,
485
,
495
,
516
,
517
,
518
,
523
,
524
,
533
,
54
7
,
548
,
556
,
567
,
571
,
572
,
582
,
592
,
602
,
615
,
54
5
,
546
,
554
,
565
,
569
,
570
,
580
,
590
,
600
,
613
,
61
6
,
626
,
639
,
643
,
647
,
651
,
652
,
665
,
666
,
679
,
61
4
,
624
,
637
,
641
,
645
,
649
,
650
,
663
,
664
,
677
,
6
80
,
693
,
694
,
711
,
712
,
725
,
726
,
727
,
728
,
729
,
6
78
,
691
,
692
,
709
,
710
,
723
,
724
,
725
,
726
,
727
,
73
3
,
736
,
747
,
755
,
763
,
790
,
795
,
806
,
810
,
814
,
73
1
,
734
,
745
,
753
,
761
,
788
,
793
,
804
,
808
,
812
,
8
21
,
859
,
862
,
869
,
877
,
898
,
919
,
930
,
959
,
964
,
8
19
,
857
,
860
,
867
,
875
,
896
,
917
,
928
,
957
,
962
,
97
4
,
979
,
989
,
992
,
995
,
998
,
1004
,
1011
,
1014
,
1036
,
97
2
,
977
,
987
,
990
,
993
,
996
,
1002
,
1009
,
1012
,
1034
,
105
4
,
1078
,
1101
,
1105
,
1109
,
1116
,
1120
,
1124
,
1213
,
1222
,
105
2
,
1076
,
1099
,
1103
,
1107
,
1114
,
1118
,
1122
,
1211
,
1220
,
122
8
,
1232
,
1239
,
1245
,
1252
,
1261
,
1270
,
1273
,
1309
,
1316
,
122
6
,
1230
,
1237
,
1243
,
1250
,
1259
,
1268
,
1271
,
1307
,
1314
,
13
20
,
1327
,
1331
,
1336
,
1341
,
1351
,
1361
,
1370
,
1380
,
1387
,
13
18
,
1325
,
1329
,
1334
,
1339
,
1349
,
1359
,
1368
,
1378
,
1385
,
13
90
,
1393
,
1399
,
1406
,
1409
,
1415
,
1418
,
1421
,
1427
,
1430
,
13
88
,
1391
,
1397
,
1404
,
1407
,
1413
,
1416
,
1419
,
1425
,
1428
,
144
5
,
1449
,
1453
,
1457
,
1461
,
1465
,
1470
,
1475
,
1480
,
1485
,
144
3
,
1447
,
1451
,
1455
,
1459
,
1463
,
1468
,
1473
,
1478
,
1483
,
14
90
,
1495
,
1500
,
1505
,
1510
,
1515
,
1520
,
1525
,
1531
,
1537
,
14
88
,
1493
,
1498
,
1503
,
1508
,
1513
,
1518
,
1523
,
1529
,
1535
,
154
3
,
1548
,
1553
,
1558
,
1563
,
1568
,
1573
,
1578
,
1583
,
1592
,
154
1
,
1546
,
1551
,
1556
,
1561
,
1566
,
1571
,
1576
,
1581
,
1590
,
1
601
,
1606
,
1619
,
1619
,
1622
,
1622
,
1628
,
1631
,
1646
,
1649
,
1
599
,
1604
,
1617
,
1617
,
1620
,
1620
,
1626
,
1629
,
1644
,
1647
,
165
7
,
1661
,
1667
,
1675
,
1691
,
1695
,
1699
,
1700
,
1706
,
1707
,
165
6
,
1660
,
1666
,
1674
,
1690
,
1694
,
1698
,
1699
,
1705
,
1706
,
170
8
,
1709
,
1710
,
1714
,
1715
,
1715
,
1715
,
1725
,
1726
,
1730
,
170
7
,
1708
,
1709
,
1713
,
1714
,
1714
,
1714
,
1724
,
1725
,
1729
,
17
30
,
1731
,
1731
,
1736
,
1739
,
1749
,
1752
,
1758
,
1759
,
1763
,
17
29
,
1730
,
1730
,
1735
,
1738
,
1748
,
1751
,
1757
,
1758
,
1762
,
177
1
,
1775
,
1785
,
1790
,
1807
,
1807
,
1812
,
1812
,
1819
,
1819
,
177
0
,
1774
,
1784
,
1789
,
1806
,
1806
,
1811
,
1811
,
1818
,
1818
,
182
7
,
1830
,
1836
,
1839
,
1845
,
1849
,
1856
,
1863
,
1870
,
1877
,
182
6
,
1829
,
1835
,
1838
,
1844
,
1848
,
1855
,
1862
,
1869
,
1876
,
188
8
,
1897
,
1901
,
1908
,
1911
,
1917
,
1917
188
7
,
1896
,
1900
,
1907
,
1910
,
1916
,
1916
};
};
#endif
#endif
...
@@ -3547,7 +3546,7 @@ yyreduce:
...
@@ -3547,7 +3546,7 @@ yyreduce:
case
109
:
case
109
:
{
{
(
yyval
.
interm
.
type
)
=
context
->
addFullySpecifiedType
((
yyvsp
[(
1
)
-
(
2
)].
interm
.
type
).
qualifier
,
(
yyvsp
[(
2
)
-
(
2
)].
interm
.
type
));
(
yyval
.
interm
.
type
)
=
context
->
addFullySpecifiedType
((
yyvsp
[(
1
)
-
(
2
)].
interm
.
type
).
qualifier
,
(
yyvsp
[(
1
)
-
(
2
)].
interm
.
type
).
layoutQualifier
,
(
yyvsp
[(
2
)
-
(
2
)].
interm
.
type
));
}
}
break
;
break
;
...
@@ -3803,35 +3802,35 @@ yyreduce:
...
@@ -3803,35 +3802,35 @@ yyreduce:
case
133
:
case
133
:
{
{
(
yyval
.
interm
.
layoutQualifier
)
=
context
->
makeLayoutQualifierFromId
((
yyvsp
[(
1
)
-
(
1
)].
interm
.
layoutQualifierId
)
);
(
yyval
.
interm
.
layoutQualifier
)
=
(
yyvsp
[(
1
)
-
(
1
)].
interm
.
layoutQualifier
);
}
}
break
;
break
;
case
134
:
case
134
:
{
{
(
yyval
.
interm
.
layoutQualifier
)
=
context
->
extendLayoutQualifier
((
yyvsp
[(
1
)
-
(
3
)].
interm
.
layoutQualifier
),
(
yyvsp
[(
3
)
-
(
3
)].
interm
.
layoutQualifierId
));
(
yyval
.
interm
.
layoutQualifier
)
=
context
->
joinLayoutQualifiers
((
yyvsp
[(
1
)
-
(
3
)].
interm
.
layoutQualifier
),
(
yyvsp
[(
3
)
-
(
3
)].
interm
.
layoutQualifier
));
}
}
break
;
break
;
case
135
:
case
135
:
{
{
(
yyval
.
interm
.
layoutQualifier
Id
)
=
context
->
addLayoutQualifierId
(
*
(
yyvsp
[(
1
)
-
(
1
)].
lex
).
string
,
(
yyvsp
[(
1
)
-
(
1
)].
lex
).
line
);
(
yyval
.
interm
.
layoutQualifier
)
=
context
->
parseLayoutQualifier
(
*
(
yyvsp
[(
1
)
-
(
1
)].
lex
).
string
,
(
yyvsp
[(
1
)
-
(
1
)].
lex
).
line
);
}
}
break
;
break
;
case
136
:
case
136
:
{
{
(
yyval
.
interm
.
layoutQualifier
Id
)
=
context
->
addLayoutQualifierId
(
*
(
yyvsp
[(
1
)
-
(
3
)].
lex
).
string
,
(
yyvsp
[(
1
)
-
(
3
)].
lex
).
line
,
*
(
yyvsp
[(
3
)
-
(
3
)].
lex
).
string
,
(
yyvsp
[(
3
)
-
(
3
)].
lex
).
i
,
(
yyvsp
[(
3
)
-
(
3
)].
lex
).
line
);
(
yyval
.
interm
.
layoutQualifier
)
=
context
->
parseLayoutQualifier
(
*
(
yyvsp
[(
1
)
-
(
3
)].
lex
).
string
,
(
yyvsp
[(
1
)
-
(
3
)].
lex
).
line
,
*
(
yyvsp
[(
3
)
-
(
3
)].
lex
).
string
,
(
yyvsp
[(
3
)
-
(
3
)].
lex
).
i
,
(
yyvsp
[(
3
)
-
(
3
)].
lex
).
line
);
}
}
break
;
break
;
case
137
:
case
137
:
{
{
(
yyval
.
interm
.
layoutQualifier
Id
)
=
context
->
addLayoutQualifierId
(
*
(
yyvsp
[(
1
)
-
(
3
)].
lex
).
string
,
(
yyvsp
[(
1
)
-
(
3
)].
lex
).
line
,
*
(
yyvsp
[(
3
)
-
(
3
)].
lex
).
string
,
(
yyvsp
[(
3
)
-
(
3
)].
lex
).
i
,
(
yyvsp
[(
3
)
-
(
3
)].
lex
).
line
);
(
yyval
.
interm
.
layoutQualifier
)
=
context
->
parseLayoutQualifier
(
*
(
yyvsp
[(
1
)
-
(
3
)].
lex
).
string
,
(
yyvsp
[(
1
)
-
(
3
)].
lex
).
line
,
*
(
yyvsp
[(
3
)
-
(
3
)].
lex
).
string
,
(
yyvsp
[(
3
)
-
(
3
)].
lex
).
i
,
(
yyvsp
[(
3
)
-
(
3
)].
lex
).
line
);
}
}
break
;
break
;
...
@@ -4216,6 +4215,7 @@ yyreduce:
...
@@ -4216,6 +4215,7 @@ yyreduce:
{
{
// ES3 Only, but errors should be handled elsewhere
// ES3 Only, but errors should be handled elsewhere
(
yyvsp
[(
2
)
-
(
4
)].
interm
.
type
).
qualifier
=
(
yyvsp
[(
1
)
-
(
4
)].
interm
.
type
).
qualifier
;
(
yyvsp
[(
2
)
-
(
4
)].
interm
.
type
).
qualifier
=
(
yyvsp
[(
1
)
-
(
4
)].
interm
.
type
).
qualifier
;
(
yyvsp
[(
2
)
-
(
4
)].
interm
.
type
).
layoutQualifier
=
(
yyvsp
[(
1
)
-
(
4
)].
interm
.
type
).
layoutQualifier
;
(
yyval
.
interm
.
typeList
)
=
context
->
addStructDeclaratorList
((
yyvsp
[(
2
)
-
(
4
)].
interm
.
type
),
(
yyvsp
[(
3
)
-
(
4
)].
interm
.
typeList
));
(
yyval
.
interm
.
typeList
)
=
context
->
addStructDeclaratorList
((
yyvsp
[(
2
)
-
(
4
)].
interm
.
type
),
(
yyvsp
[(
3
)
-
(
4
)].
interm
.
typeList
));
}
}
break
;
break
;
...
...
src/compiler/glslang_tab.h
View file @
a5efff99
...
@@ -192,8 +192,7 @@ typedef union YYSTYPE
...
@@ -192,8 +192,7 @@ typedef union YYSTYPE
union
{
union
{
TPublicType
type
;
TPublicType
type
;
TPrecision
precision
;
TPrecision
precision
;
TLayoutQualifierId
layoutQualifierId
;
TLayoutQualifier
layoutQualifier
;
TLayoutQualifier
*
layoutQualifier
;
TQualifier
qualifier
;
TQualifier
qualifier
;
TFunction
*
function
;
TFunction
*
function
;
TParameter
param
;
TParameter
param
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment