microsoft / microsoft/DirectXShaderCompiler

[SPIR-V] crash compiling shader using printf

Open
#3,768 2 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

spirv
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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.