microsoft / microsoft/DirectXShaderCompiler
[SPIR-V] crash compiling shader using printf
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 3.7k
- Forks
- 900
- Avg merge
- 2d 11h
- Merged PRs (30d)
- 44
Description
I get a crash when compiling shaders to SPIR-V with printf. It seems to be a bit inconsistent and from what I can tell there are unit tests of this that seem to pass, so I think it might be some memory corruption of some kind.
Note all the builds below have -fcgl -Vd to disable legalization, since there's a current spirv-tools issue that would crash and confuse issues: KhronosGroup/SPIRV-Tools#4219
Running dxc from the latest appveyor or latest vulkan SDK distribution and building the intrinsics.printf.hlsl test shader hits an ICE fairly consistently for me:
$ tmp/bin/dxc.exe -help | head -n 3
OVERVIEW: HLSL Compiler for Windows
Version: dxcompiler.dll: 1.7 - 1.6.0.3148 (742657ade); dxil.dll: 1.5(10.0.19041.685)
$ tmp/bin/dxc.exe -fcgl -Vd -T ps_6_0 -E main -spirv intrinsics.printf.hlsl
Internal compiler error: access violation. Attempted to read from address 0x00000154C3669308
Segmentation fault
$ /c/VulkanSDK/1.2.176.1/Bin/dxc.exe -help | head -n 3
OVERVIEW: HLSL Compiler for Windows
Version: dxcompiler.dll: 1.7 - 1.6.0.3117 (3be3d15fc); dxil.dll: 1.5(10.0.19041.685)
$ /c/VulkanSDK/1.2.176.1/Bin/dxc.exe -fcgl -Vd -T ps_6_0 -E main -spirv intrinsics.printf.hlsl
Internal compiler error: access violation. Attempted to read from address 0x00000730F44E0EB8
Segmentation fault
Weirdly if I build locally from source in debug it works. In release it works from visual studio but fails on the command line - perhaps due to differences in debug heap. Attaching to the release build gives a callstack of:
ntdll.dll!RtlFreeHeap() Unknown
ole32.dll!CRetailMalloc_Free(IMalloc * pThis, void * pv) Line 687 C++
> [Inline Frame] dxcompiler.dll!llvm::MallocAllocator::Deallocate(const void *) Line 103 C++
[Inline Frame] dxcompiler.dll!llvm::BumpPtrAllocatorImpl<llvm::MallocAllocator,4096,4096>::DeallocateSlabs(void * * I, void * * E) Line 326 C++
dxcompiler.dll!llvm::BumpPtrAllocatorImpl<llvm::MallocAllocator,4096,4096>::~BumpPtrAllocatorImpl<llvm::MallocAllocator,4096,4096>() Line 166 C++
dxcompiler.dll!clang::Sema::BuildOverloadedCallExpr(clang::Scope * S, clang::Expr * Fn, clang::UnresolvedLookupExpr * ULE, clang::SourceLocation LParenLoc, llvm::MutableArrayRef<clang::Expr *> Args, clang::SourceLocation RParenLoc, clang::Expr * ExecConfig, bool AllowTypoCorrection) Line 11082 C++
dxcompiler.dll!clang::Sema::ActOnCallExpr(clang::Scope * S, clang::Expr * Fn, clang::SourceLocation LParenLoc, llvm::MutableArrayRef<clang::Expr *> ArgExprs, clang::SourceLocation RParenLoc, clang::Expr * ExecConfig, bool IsExecConfig) Line 5001 C++
dxcompiler.dll!clang::Parser::ParsePostfixExpressionSuffix(clang::ActionResult<clang::Expr *,1> LHS) Line 1655 C++
dxcompiler.dll!clang::Parser::ParseCastExpression(bool isUnaryExpression, bool isAddressOfOperand, bool & NotCastExpr, clang::Parser::TypeCastState isTypeCast) Line 1460 C++
dxcompiler.dll!clang::Parser::ParseCastExpression(bool isUnaryExpression, bool isAddressOfOperand, clang::Parser::TypeCastState isTypeCast) Line 484 C++
dxcompiler.dll!clang::Parser::ParseAssignmentExpression(clang::Parser::TypeCastState isTypeCast) Line 178 C++
dxcompiler.dll!clang::Parser::ParseExpression(clang::Parser::TypeCastState isTypeCast) Line 122 C++
dxcompiler.dll!clang::Parser::ParseExprStatement() Line 456 C++
dxcompiler.dll!clang::Parser::ParseStatementOrDeclarationAfterAttributes(llvm::SmallVector<clang::Stmt *,32> & Stmts, bool OnlyStatement, clang::SourceLocation * TrailingElseLoc, clang::Parser::ParsedAttributesWithRange & Attrs) Line 447 C++
dxcompiler.dll!clang::Parser::ParseStatementOrDeclaration(llvm::SmallVector<clang::Stmt *,32> & Stmts, bool OnlyStatement, clang::SourceLocation * TrailingElseLoc) Line 113 C++
dxcompiler.dll!clang::Parser::ParseCompoundStatementBody(bool isStmtExpr) Line 1048 C++
dxcompiler.dll!clang::Parser::ParseFunctionStatementBody(clang::Decl * Decl, clang::Parser::ParseScope & BodyScope) Line 1985 C++
dxcompiler.dll!clang::Parser::ParseFunctionDefinition(clang::ParsingDeclarator & D, const clang::Parser::ParsedTemplateInfo & TemplateInfo, clang::Parser::LateParsedAttrList * LateParsedAttrs) Line 1177 C++
dxcompiler.dll!clang::Parser::ParseDeclGroup(clang::ParsingDeclSpec & DS, unsigned int Context, clang::SourceLocation * DeclEnd, clang::Parser::ForRangeInit * FRI) Line 2399 C++
dxcompiler.dll!clang::Parser::ParseDeclOrFunctionDefInternal(clang::Parser::ParsedAttributesWithRange & attrs, clang::ParsingDeclSpec & DS, clang::AccessSpecifier AS) Line 966 C++
dxcompiler.dll!clang::Parser::ParseDeclarationOrFunctionDefinition(clang::Parser::ParsedAttributesWithRange & attrs, clang::ParsingDeclSpec * DS, clang::AccessSpecifier AS) Line 981 C++
dxcompiler.dll!clang::Parser::ParseExternalDeclaration(clang::Parser::ParsedAttributesWithRange & attrs, clang::ParsingDeclSpec * DS) Line 839 C++
dxcompiler.dll!clang::Parser::ParseTopLevelDecl(clang::OpaquePtr<clang::DeclGroupRef> & Result) Line 606 C++
dxcompiler.dll!clang::ParseAST(clang::Sema & S, bool PrintStats, bool SkipFunctionBodies) Line 146 C++
dxcompiler.dll!clang::ASTFrontendAction::ExecuteAction() Line 554 C++
dxcompiler.dll!clang::FrontendAction::Execute() Line 469 C++
dxcompiler.dll!DxcCompiler::Compile(const DxcBuffer * pSource, const wchar_t * * pArguments, unsigned int argCount, IDxcIncludeHandler * pIncludeHandler, const _GUID & riid, void * * ppResult) Line 913 C++
dxcompiler.dll!hlsl::DxcCompilerAdapter::WrapCompile(int bPreprocess, IDxcBlob * pSource, const wchar_t * pSourceName, const wchar_t * pEntryPoint, const wchar_t * pTargetProfile, const wchar_t * * pArguments, unsigned int argCount, const DxcDefine * pDefines, unsigned int defineCount, IDxcIncludeHandler * pIncludeHandler, IDxcOperationResult * * ppResult, wchar_t * * ppDebugBlobName, IDxcBlob * * ppDebugBlob) Line 1650 C++
dxcompiler.dll!hlsl::DxcCompilerAdapter::CompileWithDebug(IDxcBlob * pSource, const wchar_t * pSourceName, const wchar_t * pEntryPoint, const wchar_t * pTargetProfile, const wchar_t * * pArguments, unsigned int argCount, const DxcDefine * pDefines, unsigned int defineCount, IDxcIncludeHandler * pIncludeHandler, IDxcOperationResult * * ppResult, wchar_t * * ppDebugBlobName, IDxcBlob * * ppDebugBlob) Line 1556 C++
dxcompiler.dll!hlsl::DxcCompilerAdapter::Compile(IDxcBlob * pSource, const wchar_t * pSourceName, const wchar_t * pEntryPoint, const wchar_t * pTargetProfile, const wchar_t * * pArguments, unsigned int argCount, const DxcDefine * pDefines, unsigned int defineCount, IDxcIncludeHandler * pIncludeHandler, IDxcOperationResult * * ppResult) Line 72 C++
dxc.exe!DxcContext::Compile() Line 790 C++
dxc.exe!dxc::main(int argc, const wchar_t * * argv_) Line 1374 C++
But I suspect that's due to heap corruption from earlier in the program. If I enable heap debugging and appverifier then I get a crash earlier:
verifier.dll!000007fef007a668() Unknown
verifier.dll!000007fef00793ea() Unknown
verifier.dll!000007fef0079736() Unknown
verifier.dll!000007fef00799cd() Unknown
verifier.dll!000007fef007873a() Unknown
ntdll.dll!RtlDebugFreeHeap() Unknown
ntdll.dll!string "Enabling heap debug options\n"() Unknown
verifier.dll!000007fef008f4e1() Unknown
ole32.dll!CRetailMalloc_Free(IMalloc * pThis, void * pv) Line 687 C++
> [Inline Frame] dxcompiler.dll!llvm::MallocAllocator::Deallocate(const void *) Line 103 C++
[Inline Frame] dxcompiler.dll!llvm::BumpPtrAllocatorImpl<llvm::MallocAllocator,4096,4096>::DeallocateSlabs(void * * I, void * * E) Line 326 C++
dxcompiler.dll!llvm::BumpPtrAllocatorImpl<llvm::MallocAllocator,4096,4096>::~BumpPtrAllocatorImpl<llvm::MallocAllocator,4096,4096>() Line 166 C++
dxcompiler.dll!clang::ASTContext::~ASTContext() Line 788 C++
dxcompiler.dll!clang::CompilerInstance::setASTContext(clang::ASTContext * Value) Line 109 C++
dxcompiler.dll!clang::FrontendAction::EndSourceFile() Line 495 C++
dxcompiler.dll!DxcCompiler::Compile(const DxcBuffer * pSource, const wchar_t * * pArguments, unsigned int argCount, IDxcIncludeHandler * pIncludeHandler, const _GUID & riid, void * * ppResult) Line 914 C++
dxcompiler.dll!hlsl::DxcCompilerAdapter::WrapCompile(int bPreprocess, IDxcBlob * pSource, const wchar_t * pSourceName, const wchar_t * pEntryPoint, const wchar_t * pTargetProfile, const wchar_t * * pArguments, unsigned int argCount, const DxcDefine * pDefines, unsigned int defineCount, IDxcIncludeHandler * pIncludeHandler, IDxcOperationResult * * ppResult, wchar_t * * ppDebugBlobName, IDxcBlob * * ppDebugBlob) Line 1650 C++
dxcompiler.dll!hlsl::DxcCompilerAdapter::CompileWithDebug(IDxcBlob * pSource, const wchar_t * pSourceName, const wchar_t * pEntryPoint, const wchar_t * pTargetProfile, const wchar_t * * pArguments, unsigned int argCount, const DxcDefine * pDefines, unsigned int defineCount, IDxcIncludeHandler * pIncludeHandler, IDxcOperationResult * * ppResult, wchar_t * * ppDebugBlobName, IDxcBlob * * ppDebugBlob) Line 1556 C++
dxcompiler.dll!hlsl::DxcCompilerAdapter::Compile(IDxcBlob * pSource, const wchar_t * pSourceName, const wchar_t * pEntryPoint, const wchar_t * pTargetProfile, const wchar_t * * pArguments, unsigned int argCount, const DxcDefine * pDefines, unsigned int defineCount, IDxcIncludeHandler * pIncludeHandler, IDxcOperationResult * * ppResult) Line 72 C++
dxc.exe!DxcContext::Compile() Line 790 C++
dxc.exe!dxc::main(int argc, const wchar_t * * argv_) Line 1374 C++
===========================================================
VERIFIER STOP 000000000000000F: pid 0xC958: corrupted suffix pattern
00000000022C1000 : Heap handle
00000000033FA290 : Heap block
0000000000001000 : Block size
00000000033FB290 : corruption address
===========================================================
This verifier stop is not continuable. Process will be terminated
when you use the `go' debugger command.
===========================================================
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reproducing the crash with tools/clang/test/CodeGenSPIRV/intrinsics.printf.hlsl using dxc -fcgl -Vd -T ps_6_0 -E main -spirv. Then inspect the compiler path shown in the callstack, especially Sema::BuildOverloadedCallExpr and AST cleanup, alongside the existing printf test. Done means the shader compiles without heap corruption or an access violation and the regression is covered by a test.
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