KhronosGroup / KhronosGroup/glslang

Crash with the `--no-link` option

Open
#4,030 7 comments 0 reactions 0 assignees View on GitHub
bug sev:crash
Dominant language
C++
Stars
3.6k
Forks
989
Avg merge
1d 2h
Merged PRs (30d)
31

Description

Hi,

I'm trying to compile two parts of a single shader separately with the `--no-link` option, and then link them together using `spirv-link`, but `glslang` crashes with a null pointer dereference (or emits an error, depending on the presence of `main()`).

**UPD:** *I made a mistake when testing the first compiler invocation (`main.frag`) which suppressed the error message. If needed, I'll create a separate issue for this, but it probably makes sense to figure out if this usage pattern is even valid first.*

The general idea is to prepare a compiled (but not linked) shader offline, with one function missing. Then at runtime, generate and compile that missing function (based on a material definition), and link the SPIR-V files together. `--no-link` seemed like the correct option for the job.

Or perhaps there's a different way to achieve such a result?

Here's the code:
```glsl
// interface.glsl
#ifndef INTERFACE_GLSL
#define INTERFACE_GLSL
vec4 do_some_math(vec4 src); // implemented in main.frag
vec4 calculate_color(vec4 arg); // implemented in impl.glsl
#endif // INTERFACE_GLSL
```

```glsl
// main.frag
#extension GL_GOOGLE_include_directive : require
#include "interface.glsl"
layout(location = 0) in vec4 frag_arg;
layout(location = 0) out vec4 out_color;
vec4 do_some_math(vec4 arg) {
return arg + 1.0;
}
void main() {
out_color = calculate_color(frag_arg);
}
```

```glsl
// impl.glsl
#extension GL_GOOGLE_include_directive : require
#include "interface.glsl"
vec4 calculate_color(vec4 arg) {
return clamp(do_some_math(arg), 0.0, 2.0) * 0.5;
}
```

This invocation fails with `ERROR: main.frag:14: '' : main function cannot be exported`:
```shell
glslang -o main.frag.spv --glsl-version 460 --target-env vulkan1.3 --no-link -S frag main.frag
```

This invocation crashes:
```shell
glslang -o impl.glsl.spv --glsl-version 460 --target-env vulkan1.3 --no-link -S frag impl.glsl
```

The crash stack trace (from 3289b1d61b69a6c66c4b7cd2c6d3ab2a6df031e5):
```
[glslang.exe] spv::Instruction::getOpCode() spvIR.h:217
[glslang.exe] spv::Module::getStorageClass(unsigned int) spvIR.h:577 // idToInstruction[typeId] is NULL
[glslang.exe] spv::Builder::getTypeStorageClass(unsigned int) SpvBuilder.h:288
[glslang.exe] spv::Builder::getStorageClass(unsigned int) SpvBuilder.h:342
[glslang.exe] spv::Builder::accessChainLoad(Decoration, Decoration, Decoration, unsigned int, MemoryAccessMask, Scope, unsigned int) SpvBuilder.cpp:4349
[glslang.exe] `anonymous namespace'::TGlslangToSpvTraverser::accessChainLoad(const glslang::TType &) GlslangToSpv.cpp:5864
[glslang.exe] `anonymous namespace'::TGlslangToSpvTraverser::visitAggregate(TVisit, glslang::TIntermAggregate *) GlslangToSpv.cpp:4007
[glslang.exe] glslang::TIntermAggregate::traverse(glslang::TIntermTraverser *) IntermTraverse.cpp:159
[glslang.exe] `anonymous namespace'::TGlslangToSpvTraverser::visitBinary(TVisit, glslang::TIntermBinary *) GlslangToSpv.cpp:2476
[glslang.exe] glslang::TIntermBinary::traverse(glslang::TIntermTraverser *) IntermTraverse.cpp:92
[glslang.exe] `anonymous namespace'::TGlslangToSpvTraverser::visitBranch(TVisit, glslang::TIntermBranch *) GlslangToSpv.cpp:4851
[glslang.exe] glslang::TIntermBranch::traverse(glslang::TIntermTraverser *) IntermTraverse.cpp:271
[glslang.exe] glslang::TIntermAggregate::traverse(glslang::TIntermTraverser *) IntermTraverse.cpp:175
[glslang.exe] glslang::TIntermAggregate::traverse(glslang::TIntermTraverser *) IntermTraverse.cpp:175
[glslang.exe] `anonymous namespace'::TGlslangToSpvTraverser::visitFunctions(const glslang::TVector &) GlslangToSpv.cpp:6392
[glslang.exe] `anonymous namespace'::TGlslangToSpvTraverser::visitAggregate(TVisit, glslang::TIntermAggregate *) GlslangToSpv.cpp:3060
[glslang.exe] glslang::TIntermAggregate::traverse(glslang::TIntermTraverser *) IntermTraverse.cpp:159
[glslang.exe] glslang::GlslangToSpv(const glslang::TIntermediate &, std::vector &, spv::SpvBuildLogger *, glslang::SpvOptions *) GlslangToSpv.cpp:11084
[glslang.exe] CompileAndLinkShaderUnits(vector >) StandAlone.cpp:1578
[glslang.exe] CompileAndLinkShaderFiles(glslang::TWorklist &) StandAlone.cpp:1674
[glslang.exe] singleMain() StandAlone.cpp:1757
[glslang.exe] main(int, char **) StandAlone.cpp:1811
[glslang.exe] invoke_main() 0x00007ff6bda39a79
[glslang.exe] __scrt_common_main_seh() 0x00007ff6bda39962
[glslang.exe] __scrt_common_main() 0x00007ff6bda3981e
[glslang.exe] mainCRTStartup(void *) 0x00007ff6bda39b0e
[kernel32.dll] BaseThreadInitThunk 0x00007ffd2769e8d7
[ntdll.dll] RtlUserThreadStart 0x00007ffd2983c34c
```

Contributor guide

Open the contributing guide

Research direction

Reproduce both commands with the supplied interface.glsl, main.frag, and impl.glsl inputs, then follow the stack through StandAlone.cpp, GlslangToSpv.cpp, and SpvBuilder.cpp. Determine whether --no-link supports this separate-compilation pattern; done means the invocation either behaves according to a defined rule or reports an error instead of dereferencing a null pointer.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.