Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
G
glslang
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
glslang
Commits
6a60c2f9
Commit
6a60c2f9
authored
Dec 08, 2016
by
John Kessenich
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Linker: Walk the call graph to report an error on missing bodies.
parent
e795cc91
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
228 additions
and
8 deletions
+228
-8
GlslangToSpv.cpp
SPIRV/GlslangToSpv.cpp
+2
-2
100scope.vert.out
Test/baseResults/100scope.vert.out
+2
-0
110scope.vert.out
Test/baseResults/110scope.vert.out
+4
-0
300scope.vert.out
Test/baseResults/300scope.vert.out
+2
-0
430scope.vert.out
Test/baseResults/430scope.vert.out
+2
-0
missingBodies.vert.out
Test/baseResults/missingBodies.vert.out
+117
-0
missingBodies.vert
Test/missingBodies.vert
+24
-0
revision.h
glslang/Include/revision.h
+2
-2
linkValidate.cpp
glslang/MachineIndependent/linkValidate.cpp
+67
-3
localintermediate.h
glslang/MachineIndependent/localintermediate.h
+5
-1
Link.FromFile.cpp
gtests/Link.FromFile.cpp
+1
-0
No files found.
SPIRV/GlslangToSpv.cpp
View file @
6a60c2f9
...
...
@@ -1352,7 +1352,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
// anything else gets there, so visit out of order, doing them all now.
makeGlobalInitializers
(
node
->
getAsAggregate
()
->
getSequence
());
// Initializers are done, don't want to visit again, but functions link objects need to be processed,
// Initializers are done, don't want to visit again, but functions
and
link objects need to be processed,
// so do them manually.
visitFunctions
(
node
->
getAsAggregate
()
->
getSequence
());
...
...
@@ -2634,7 +2634,7 @@ void TGlslangToSpvTraverser::visitFunctions(const glslang::TIntermSequence& glsl
{
for
(
int
f
=
0
;
f
<
(
int
)
glslFunctions
.
size
();
++
f
)
{
glslang
::
TIntermAggregate
*
node
=
glslFunctions
[
f
]
->
getAsAggregate
();
if
(
node
&&
(
node
->
getOp
()
==
glslang
::
EOpFunction
||
node
->
getOp
()
==
glslang
::
EOpLinkerObjects
))
if
(
node
&&
(
node
->
getOp
()
==
glslang
::
EOpFunction
||
node
->
getOp
()
==
glslang
::
EOpLinkerObjects
))
node
->
traverse
(
this
);
}
}
...
...
Test/baseResults/100scope.vert.out
View file @
6a60c2f9
...
...
@@ -128,6 +128,8 @@ ERROR: node is still EOpNull!
Linked vertex stage:
ERROR: Linking vertex stage: No function definition (body) found:
g(
Shader version: 100
ERROR: node is still EOpNull!
...
...
Test/baseResults/110scope.vert.out
View file @
6a60c2f9
...
...
@@ -130,6 +130,10 @@ ERROR: node is still EOpNull!
Linked vertex stage:
ERROR: Linking vertex stage: No function definition (body) found:
sin(f1;
ERROR: Linking vertex stage: No function definition (body) found:
g(
Shader version: 110
ERROR: node is still EOpNull!
...
...
Test/baseResults/300scope.vert.out
View file @
6a60c2f9
...
...
@@ -131,6 +131,8 @@ ERROR: node is still EOpNull!
Linked vertex stage:
ERROR: Linking vertex stage: No function definition (body) found:
g(
Shader version: 300
ERROR: node is still EOpNull!
...
...
Test/baseResults/430scope.vert.out
View file @
6a60c2f9
...
...
@@ -127,6 +127,8 @@ ERROR: node is still EOpNull!
Linked vertex stage:
ERROR: Linking vertex stage: No function definition (body) found:
g(
Shader version: 430
ERROR: node is still EOpNull!
...
...
Test/baseResults/missingBodies.vert.out
0 → 100755
View file @
6a60c2f9
missingBodies.vert
Warning, version 450 is not yet complete; most version-specific features are present, but some are missing.
Shader version: 450
0:? Sequence
0:4 Function Definition: foo( (global void)
0:4 Function Parameters:
0:4 Sequence
0:4 Function Call: bar( (global void)
0:8 Function Definition: C(i1;i1; (global void)
0:8 Function Parameters:
0:8 '' (in int)
0:8 '' (in int)
0:10 Function Definition: A( (global void)
0:10 Function Parameters:
0:10 Sequence
0:10 Function Call: B( (global void)
0:10 Function Call: C(i1; (global void)
0:10 Constant:
0:10 1 (const int)
0:10 Function Call: C(b1; (global void)
0:10 Constant:
0:10 true (const bool)
0:10 Function Call: C(i1;i1; (global void)
0:10 Constant:
0:10 1 (const int)
0:10 Constant:
0:10 2 (const int)
0:12 Function Definition: main( (global void)
0:12 Function Parameters:
0:14 Sequence
0:14 Function Call: foo( (global void)
0:15 Function Call: C(b1; (global void)
0:15 Constant:
0:15 true (const bool)
0:20 Sequence
0:20 move second child to first child (temp int)
0:20 'f1' (global int)
0:20 Function Call: ret1( (global int)
0:22 Function Definition: ret2( (global int)
0:22 Function Parameters:
0:22 Sequence
0:22 Branch: Return with expression
0:22 Constant:
0:22 3 (const int)
0:24 Sequence
0:24 move second child to first child (temp int)
0:24 'f2' (global int)
0:24 Function Call: ret2( (global int)
0:? Linker Objects
0:? 'f1' (global int)
0:? 'f2' (global int)
0:? 'gl_VertexID' (gl_VertexId int VertexId)
0:? 'gl_InstanceID' (gl_InstanceId int InstanceId)
Linked vertex stage:
ERROR: Linking vertex stage: No function definition (body) found:
ret1(
ERROR: Linking vertex stage: No function definition (body) found:
C(b1;
ERROR: Linking vertex stage: No function definition (body) found:
bar(
Shader version: 450
0:? Sequence
0:4 Function Definition: foo( (global void)
0:4 Function Parameters:
0:4 Sequence
0:4 Function Call: bar( (global void)
0:8 Function Definition: C(i1;i1; (global void)
0:8 Function Parameters:
0:8 '' (in int)
0:8 '' (in int)
0:10 Function Definition: A( (global void)
0:10 Function Parameters:
0:10 Sequence
0:10 Function Call: B( (global void)
0:10 Function Call: C(i1; (global void)
0:10 Constant:
0:10 1 (const int)
0:10 Function Call: C(b1; (global void)
0:10 Constant:
0:10 true (const bool)
0:10 Function Call: C(i1;i1; (global void)
0:10 Constant:
0:10 1 (const int)
0:10 Constant:
0:10 2 (const int)
0:12 Function Definition: main( (global void)
0:12 Function Parameters:
0:14 Sequence
0:14 Function Call: foo( (global void)
0:15 Function Call: C(b1; (global void)
0:15 Constant:
0:15 true (const bool)
0:20 Sequence
0:20 move second child to first child (temp int)
0:20 'f1' (global int)
0:20 Function Call: ret1( (global int)
0:22 Function Definition: ret2( (global int)
0:22 Function Parameters:
0:22 Sequence
0:22 Branch: Return with expression
0:22 Constant:
0:22 3 (const int)
0:24 Sequence
0:24 move second child to first child (temp int)
0:24 'f2' (global int)
0:24 Function Call: ret2( (global int)
0:? Linker Objects
0:? 'f1' (global int)
0:? 'f2' (global int)
0:? 'gl_VertexID' (gl_VertexId int VertexId)
0:? 'gl_InstanceID' (gl_InstanceId int InstanceId)
Test/missingBodies.vert
0 → 100644
View file @
6a60c2f9
#version 450
void
bar
();
void
foo
()
{
bar
();
}
void
B
();
void
C
(
int
);
void
C
(
int
,
int
)
{
}
void
C
(
bool
);
void
A
()
{
B
();
C
(
1
);
C
(
true
);
C
(
1
,
2
);
}
void
main
()
{
foo
();
C
(
true
);
}
int
ret1
();
int
f1
=
ret1
();
int
ret2
()
{
return
3
;
}
int
f2
=
ret2
();
glslang/Include/revision.h
View file @
6a60c2f9
...
...
@@ -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.16
7
6"
#define GLSLANG_DATE "0
5
-Dec-2016"
#define GLSLANG_REVISION "Overload400-PrecQual.16
8
6"
#define GLSLANG_DATE "0
8
-Dec-2016"
glslang/MachineIndependent/linkValidate.cpp
View file @
6a60c2f9
...
...
@@ -94,7 +94,7 @@ void TIntermediate::merge(TInfoSink& infoSink, TIntermediate& unit)
callGraph
.
insert
(
callGraph
.
end
(),
unit
.
callGraph
.
begin
(),
unit
.
callGraph
.
end
());
if
(
originUpperLeft
!=
unit
.
originUpperLeft
||
pixelCenterInteger
!=
unit
.
pixelCenterInteger
)
error
(
infoSink
,
"gl_FragCoord redeclarations must match across shaders
\n
"
);
error
(
infoSink
,
"gl_FragCoord redeclarations must match across shaders"
);
if
(
!
earlyFragmentTests
)
earlyFragmentTests
=
unit
.
earlyFragmentTests
;
...
...
@@ -390,8 +390,9 @@ void TIntermediate::finalCheck(TInfoSink& infoSink)
if
(
numPushConstants
>
1
)
error
(
infoSink
,
"Only one push_constant block is allowed per stage"
);
// recursion checking
// recursion
and missing body
checking
checkCallGraphCycles
(
infoSink
);
checkCallGraphBodies
(
infoSink
);
// overlap/alias/missing I/O, etc.
inOutLocationCheck
(
infoSink
);
...
...
@@ -502,7 +503,7 @@ void TIntermediate::finalCheck(TInfoSink& infoSink)
//
void
TIntermediate
::
checkCallGraphCycles
(
TInfoSink
&
infoSink
)
{
//
Reset everything, once
.
//
Clear fields we'll use for this
.
for
(
TGraph
::
iterator
call
=
callGraph
.
begin
();
call
!=
callGraph
.
end
();
++
call
)
{
call
->
visited
=
false
;
call
->
currentPath
=
false
;
...
...
@@ -578,6 +579,69 @@ void TIntermediate::checkCallGraphCycles(TInfoSink& infoSink)
}
//
// See which functions are reachable from the entry point and which have bodies.
// Reachable ones with missing bodies are errors.
//
void
TIntermediate
::
checkCallGraphBodies
(
TInfoSink
&
infoSink
)
{
// Clear fields we'll use for this.
for
(
TGraph
::
iterator
call
=
callGraph
.
begin
();
call
!=
callGraph
.
end
();
++
call
)
{
call
->
visited
=
false
;
call
->
calleeBodyPosition
=
-
1
;
}
// The top level of the AST includes function definitions (bodies).
// Compare these to function calls in the call graph.
// We'll end up knowing which have bodies, and if so,
// how to map the call-graph node to the location in the AST.
TIntermSequence
&
functionSequence
=
getTreeRoot
()
->
getAsAggregate
()
->
getSequence
();
for
(
int
f
=
0
;
f
<
(
int
)
functionSequence
.
size
();
++
f
)
{
glslang
::
TIntermAggregate
*
node
=
functionSequence
[
f
]
->
getAsAggregate
();
if
(
node
&&
(
node
->
getOp
()
==
glslang
::
EOpFunction
))
{
for
(
TGraph
::
iterator
call
=
callGraph
.
begin
();
call
!=
callGraph
.
end
();
++
call
)
{
if
(
call
->
callee
==
node
->
getName
())
call
->
calleeBodyPosition
=
f
;
}
}
}
// Start call-graph traversal by visiting the entry point nodes.
for
(
TGraph
::
iterator
call
=
callGraph
.
begin
();
call
!=
callGraph
.
end
();
++
call
)
{
if
(
call
->
caller
.
compare
(
getEntryPointMangledName
().
c_str
())
==
0
)
call
->
visited
=
true
;
}
// Propagate 'visited' through the call-graph to every part of the graph it
// can reach (seeded with the entry-point setting above).
bool
changed
;
do
{
changed
=
false
;
for
(
auto
call1
=
callGraph
.
begin
();
call1
!=
callGraph
.
end
();
++
call1
)
{
if
(
call1
->
visited
)
{
for
(
TGraph
::
iterator
call2
=
callGraph
.
begin
();
call2
!=
callGraph
.
end
();
++
call2
)
{
if
(
!
call2
->
visited
)
{
if
(
call1
->
callee
==
call2
->
caller
)
{
changed
=
true
;
call2
->
visited
=
true
;
}
}
}
}
}
}
while
(
changed
);
// Any call-graph node set to visited but without a callee body is an error.
for
(
TGraph
::
iterator
call
=
callGraph
.
begin
();
call
!=
callGraph
.
end
();
++
call
)
{
if
(
call
->
visited
)
{
if
(
call
->
calleeBodyPosition
==
-
1
)
{
error
(
infoSink
,
"No function definition (body) found: "
);
infoSink
.
info
<<
" "
<<
call
->
callee
<<
"
\n
"
;
}
}
}
}
//
// Satisfy rules for location qualifiers on inputs and outputs
//
void
TIntermediate
::
inOutLocationCheck
(
TInfoSink
&
infoSink
)
...
...
glslang/MachineIndependent/localintermediate.h
View file @
6a60c2f9
...
...
@@ -67,7 +67,9 @@ struct TVectorFields {
// by TIntermediate.
//
// Used for detecting recursion: A "call" is a pair: <caller, callee>.
// Used for call-graph algorithms for detecting recursion, missing bodies, and dead bodies.
// A "call" is a pair: <caller, callee>.
// There can be duplicates. General assumption is the list is small.
struct
TCall
{
TCall
(
const
TString
&
pCaller
,
const
TString
&
pCallee
)
:
caller
(
pCaller
),
callee
(
pCallee
)
{
}
TString
caller
;
...
...
@@ -75,6 +77,7 @@ struct TCall {
bool
visited
;
bool
currentPath
;
bool
errorGiven
;
int
calleeBodyPosition
;
};
// A generic 1-D range.
...
...
@@ -393,6 +396,7 @@ protected:
void
mergeImplicitArraySizes
(
TType
&
,
const
TType
&
);
void
mergeErrorCheck
(
TInfoSink
&
,
const
TIntermSymbol
&
,
const
TIntermSymbol
&
,
bool
crossStage
);
void
checkCallGraphCycles
(
TInfoSink
&
);
void
checkCallGraphBodies
(
TInfoSink
&
);
void
inOutLocationCheck
(
TInfoSink
&
);
TIntermSequence
&
findLinkerObjects
()
const
;
bool
userOutputUsed
()
const
;
...
...
gtests/Link.FromFile.cpp
View file @
6a60c2f9
...
...
@@ -99,6 +99,7 @@ INSTANTIATE_TEST_CASE_P(
{
"150.tesc"
,
"150.tese"
,
"400.tesc"
,
"400.tese"
,
"410.tesc"
,
"420.tesc"
,
"420.tese"
},
{
"max_vertices_0.geom"
},
{
"es-link1.frag"
,
"es-link2.frag"
},
{
"missingBodies.vert"
}
})),
);
// clang-format on
...
...
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