Casting subclass to parent of three class heirarchy causes crashes
The following shader which attempts to cast a variable of type C to its immediate parent, type B while passing an argument crashes DXC. If the only classes are B and C, this works fine. If there is a parent class to B, then it fails. Passing the argument as class C works fine as well.
struct A {
float4 stuff;
};
struct B : A {
float4 gimme() {return stuff;}
};
struct C : B {
void dostuff() {stuff = 0;}
};
float4 f(B thing1) { // THIS IS THE PROBLEM
return thing1.gimme();
}
float4 main() : SV_Target
{
C thing2;
thing2.stuff = float4(1,2,3,4);
return f(thing2);
}
A slightly altered shader gives a slightly different crash location that comes a bit earlier.
struct A {
float4 stuff;
};
struct B : A {
Texture2D tex; // THIS IS WHAT'S NEW
float4 gimme() {return stuff;}
};
struct C : B {
void dostuff() {stuff = 0;}
};
float4 f(B thing1) { // THIS IS THE PROBLEM
return thing1.gimme();
}
float4 main() : SV_Target
{
C thing2;
thing2.stuff = float4(1,2,3,4);
return f(thing2);
}
Both of these crashes are in codegen and seem to stem from the expectation that casts of this sort will be limited to simple types rather than structs.
Compiler Explorer: https://godbolt.org/z/33nncaE4z
Crash callstack:
(lldb) bt
* thread #1, name = 'dxc', stop reason = signal SIGABRT
frame #0: 0x00007fffe64909fc libc.so.6 at pthread_kill.c:44
frame #1: 0x00007fffe64909b0 libc.so.6 at pthread_kill.c:78
frame #2: 0x00007fffe64909b0 libc.so.6 at pthread_kill.c:89
frame #3: 0x00007fffe643c476 libc.so.6 at raise.c:26
frame #4: 0x00007fffe64227f3 libc.so.6 at abort.c:79
frame #5: 0x00007fffe642271b libc.so.6 __assert_fail_base.cold:`__assert_fail_base.cold + 15 at assert.c:92
frame #6: 0x00007fffe6433e96 libc.so.6 at assert.c:101
frame #7: 0x00007fffef77e577 libdxcompiler.so llvm::ArrayRef<llvm::Value*>::operator[]:`llvm::ArrayRef<llvm::Value*>::operator[](this=0x00007fffffff19c0, Index=0) const + 135 at ArrayRef.h:197
* frame #8: 0x00007ffff14b5d19 libdxcompiler.so (anonymous namespace)::CGMSHLSLRuntime::ConvertAndStoreElements:`(anonymous namespace)::CGMSHLSLRuntime::ConvertAndStoreElements(this=0x00005555570bad30, CGF=0x00007fffffff6eb8, SrcVals=ArrayRef<llvm::Value *> @ 0x00007fffffff19c0, SrcQualTys=ArrayRef<clang::QualType> @ 0x00007fffffff19b0, DstPtrs=ArrayRef<llvm::Value *> @ 0x00007fffffff19e0, DstQualTys=ArrayRef<clang::QualType> @ 0x00007fffffff19f0) + 345 at CGHLSLMS.cpp:5752
frame #9: 0x00007ffff1482768 libdxcompiler.so (anonymous namespace)::CGMSHLSLRuntime::EmitHLSLFlatConversionAggregateCopy:`(anonymous namespace)::CGMSHLSLRuntime::EmitHLSLFlatConversionAggregateCopy(this=0x00005555570bad30, CGF=0x00007fffffff6eb8, SrcPtr=0x000055555711bf28, SrcTy=QualType @ 0x00007fffffff1f68, DestPtr=0x000055555711f878, DestTy=QualType @ 0x00007fffffff1f60) + 4968 at CGHLSLMS.cpp:6050
frame #10: 0x00007ffff13271a3 libdxcompiler.so (anonymous namespace)::AggExprEmitter::VisitCastExpr:`(anonymous namespace)::AggExprEmitter::VisitCastExpr(this=0x00007fffffff31c0, E=0x0000555557108be0) + 8915 at CGExprAgg.cpp:754
frame #11: 0x00007ffff131cfa9 libdxcompiler.so clang::StmtVisitorBase<clang::make_ptr, (anonymous namespace)::AggExprEmitter, void>::VisitImplicitCastExpr:`clang::StmtVisitorBase<clang::make_ptr, (anonymous namespace)::AggExprEmitter, void>::VisitImplicitCastExpr(this=0x00007fffffff31c0, S=0x0000555557108be0) + 105 at StmtNodes.inc:399
frame #12: 0x00007ffff13165da libdxcompiler.so clang::StmtVisitorBase<clang::make_ptr, (anonymous namespace)::AggExprEmitter, void>::Visit:`clang::StmtVisitorBase<clang::make_ptr, (anonymous namespace)::AggExprEmitter, void>::Visit(this=0x00007fffffff31c0, S=0x0000555557108be0) + 7098 at StmtNodes.inc:399
frame #13: 0x00007ffff13126fc libdxcompiler.so (anonymous namespace)::AggExprEmitter::Visit:`(anonymous namespace)::AggExprEmitter::Visit(this=0x00007fffffff31c0, E=0x0000555557108be0) + 140 at CGExprAgg.cpp:105
frame #14: 0x00007ffff1311e61 libdxcompiler.so clang::CodeGen::CodeGenFunction::EmitAggExpr:`clang::CodeGen::CodeGenFunction::EmitAggExpr(this=0x00007fffffff6eb8, E=0x0000555557108be0, Slot=AggValueSlot @ 0x00007fffffff3200) + 529 at CGExprAgg.cpp:1505
frame #15: 0x00007ffff11c311b libdxcompiler.so clang::CodeGen::CodeGenFunction::EmitAnyExpr:`clang::CodeGen::CodeGenFunction::EmitAnyExpr(this=0x00007fffffff6eb8, E=0x0000555557108be0, aggSlot=AggValueSlot @ 0x00007fffffff3300, ignoreResult=false) + 747 at CGExpr.cpp:134
frame #16: 0x00007ffff11c4309 libdxcompiler.so clang::CodeGen::CodeGenFunction::EmitAnyExprToTemp:`clang::CodeGen::CodeGenFunction::EmitAnyExprToTemp(this=0x00007fffffff6eb8, E=0x0000555557108be0) + 313 at CGExpr.cpp:147
frame #17: 0x00007ffff147bea0 libdxcompiler.so (anonymous namespace)::CGMSHLSLRuntime::EmitHLSLOutParamConversionInit:`(anonymous namespace)::CGMSHLSLRuntime::EmitHLSLOutParamConversionInit(this=0x00005555570bad30, CGF=0x00007fffffff6eb8, FD=0x00005555571008b8, E=0x0000555557108bb0, castArgList=0x00007fffffff4c78, argList=0x00007fffffff4948, lifetimeCleanupList=0x00007fffffff49a0, TmpArgMap=0x00007fffffff48b8)> const&) + 4128 at CGHLSLMS.cpp:6343
frame #18: 0x00007ffff11ecb64 libdxcompiler.so clang::CodeGen::CodeGenFunction::EmitCall:`clang::CodeGen::CodeGenFunction::EmitCall(this=0x00007fffffff6eb8, CalleeType=QualType @ 0x00007fffffff5198, Callee=0x000055555711f3e8, E=0x0000555557108bb0, ReturnValue=ReturnValueSlot @ 0x00007fffffff5190, TargetDecl=0x00005555571008b8, Chain=0x0000000000000000) + 4308 at CGExpr.cpp:3960
frame #19: 0x00007ffff11eba6a libdxcompiler.so clang::CodeGen::CodeGenFunction::EmitCallExpr:`clang::CodeGen::CodeGenFunction::EmitCallExpr(this=0x00007fffffff6eb8, E=0x0000555557108bb0, ReturnValue=ReturnValueSlot @ 0x00007fffffff5448) + 2634 at CGExpr.cpp:3719
frame #20: 0x00007ffff12261f9 libdxcompiler.so (anonymous namespace)::ScalarExprEmitter::VisitCallExpr:`(anonymous namespace)::ScalarExprEmitter::VisitCallExpr(this=0x00007fffffff5fb0, E=0x0000555557108bb0) + 505 at CGExprScalar.cpp:364
frame #21: 0x00007ffff121c55e libdxcompiler.so clang::StmtVisitorBase<clang::make_ptr, (anonymous namespace)::ScalarExprEmitter, llvm::Value*>::Visit:`clang::StmtVisitorBase<clang::make_ptr, (anonymous namespace)::ScalarExprEmitter, llvm::Value*>::Visit(this=0x00007fffffff5fb0, S=0x0000555557108bb0) + 6702 at StmtNodes.inc:305
frame #22: 0x00007ffff120cb9d libdxcompiler.so (anonymous namespace)::ScalarExprEmitter::Visit:`(anonymous namespace)::ScalarExprEmitter::Visit(this=0x00007fffffff5fb0, E=0x0000555557108bb0) + 2877 at CGExprScalar.cpp:230
frame #23: 0x00007ffff120bf1f libdxcompiler.so clang::CodeGen::CodeGenFunction::EmitScalarExpr:`clang::CodeGen::CodeGenFunction::EmitScalarExpr(this=0x00007fffffff6eb8, E=0x0000555557108bb0, IgnoreResultAssign=false) + 335 at CGExprScalar.cpp:3926
frame #24: 0x00007ffff133f554 libdxcompiler.so clang::CodeGen::CodeGenFunction::EmitReturnStmt:`clang::CodeGen::CodeGenFunction::EmitReturnStmt(this=0x00007fffffff6eb8, S=0x0000555557108c00) + 2340 at CGStmt.cpp:1164
frame #25: 0x00007ffff133b8a3 libdxcompiler.so clang::CodeGen::CodeGenFunction::EmitStmt:`clang::CodeGen::CodeGenFunction::EmitStmt(this=0x00007fffffff6eb8, S=0x0000555557108c00) + 1971 at CGStmt.cpp:138
frame #26: 0x00007ffff1342f1c libdxcompiler.so clang::CodeGen::CodeGenFunction::EmitCompoundStmtWithoutScope:`clang::CodeGen::CodeGenFunction::EmitCompoundStmtWithoutScope(this=0x00007fffffff6eb8, S=0x0000555557108c18, GetLast=false, AggSlot=AggValueSlot @ 0x00007fffffff6700) + 380 at CGStmt.cpp:305
frame #27: 0x00007ffff117db21 libdxcompiler.so clang::CodeGen::CodeGenFunction::EmitFunctionBody:`clang::CodeGen::CodeGenFunction::EmitFunctionBody(this=0x00007fffffff6eb8, Args=0x00007fffffff6ba0, Body=0x0000555557108c18) + 161 at CodeGenFunction.cpp:811
frame #28: 0x00007ffff117ec71 libdxcompiler.so clang::CodeGen::CodeGenFunction::GenerateCode:`clang::CodeGen::CodeGenFunction::GenerateCode(this=0x00007fffffff6eb8, GD=GlobalDecl @ 0x00007fffffff6c58, Fn=0x0000555557109f58, FnInfo=0x00005555570fe9f0) + 4065 at CodeGenFunction.cpp:932
frame #29: 0x00007ffff0f768fb libdxcompiler.so clang::CodeGen::CodeGenModule::EmitGlobalFunctionDefinition:`clang::CodeGen::CodeGenModule::EmitGlobalFunctionDefinition(this=0x00005555570b86d0, GD=GlobalDecl @ 0x00007fffffff7978, GV=0x0000555557109f58) + 3483 at CodeGenModule.cpp:2620
frame #30: 0x00007ffff0f70157 libdxcompiler.so clang::CodeGen::CodeGenModule::EmitGlobalDefinition:`clang::CodeGen::CodeGenModule::EmitGlobalDefinition(this=0x00005555570b86d0, GD=GlobalDecl @ 0x00007fffffff7b28, GV=0x0000000000000000) + 1463 at CodeGenModule.cpp:1603
frame #31: 0x00007ffff0f747f5 libdxcompiler.so clang::CodeGen::CodeGenModule::EmitGlobal:`clang::CodeGen::CodeGenModule::EmitGlobal(this=0x00005555570b86d0, GD=GlobalDecl @ 0x00007fffffff7d28) + 1749 at CodeGenModule.cpp:1451
frame #32: 0x00007ffff0f7aa2e libdxcompiler.so clang::CodeGen::CodeGenModule::EmitTopLevelDecl:`clang::CodeGen::CodeGenModule::EmitTopLevelDecl(this=0x00005555570b86d0, D=0x0000555557108680) + 462 at CodeGenModule.cpp:3392
frame #33: 0x00007ffff15b69f8 libdxcompiler.so (anonymous namespace)::CodeGeneratorImpl::HandleTopLevelDecl:`(anonymous namespace)::CodeGeneratorImpl::HandleTopLevelDecl(this=0x00005555570b3680, DG=DeclGroupRef @ 0x00007fffffff7f30) + 360 at ModuleBuilder.cpp:134
frame #34: 0x00007ffff0e85559 libdxcompiler.so clang::BackendConsumer::HandleTopLevelDecl:`clang::BackendConsumer::HandleTopLevelDecl(this=0x00005555570b3580, D=DeclGroupRef @ 0x00007fffffff8018) + 505 at CodeGenAction.cpp:120
frame #35: 0x00007ffff38b1262 libdxcompiler.so clang::ParseAST:`clang::ParseAST(S=0x00005555570b4240, PrintStats=false, SkipFunctionBodies=false) + 1746 at ParseAST.cpp:148
frame #36: 0x00007ffff16370e5 libdxcompiler.so clang::ASTFrontendAction::ExecuteAction:`clang::ASTFrontendAction::ExecuteAction(this=0x00007fffffffa1e0) + 725 at FrontendAction.cpp:554
frame #37: 0x00007ffff0e82393 libdxcompiler.so clang::CodeGenAction::ExecuteAction:`clang::CodeGenAction::ExecuteAction(this=0x00007fffffffa1e0) + 3715 at CodeGenAction.cpp:807
frame #38: 0x00007ffff16365cf libdxcompiler.so clang::FrontendAction::Execute:`clang::FrontendAction::Execute(this=0x00007fffffffa1e0) + 303 at FrontendAction.cpp:455
frame #39: 0x00007fffef57d743 libdxcompiler.so DxcCompiler::Compile:`DxcCompiler::Compile(this=0x00005555570738a0, pSource=0x00007fffffffc970, pArguments=0x0000555557074220, argCount=5 0x00000005, pIncludeHandler=0x0000555557073570, riid=0x0000555555b06c40, ppResult=0x00007fffffffbe60) + 22435 at dxcompilerobj.cpp:984
frame #40: 0x00007fffef569450 libdxcompiler.so hlsl::DxcCompilerAdapter::WrapCompile:`hlsl::DxcCompilerAdapter::WrapCompile(this=0x0000555557073cc0, bPreprocess=NO, pSource=0x0000555557073d70, pSourceName=L"crash.hlsl", pEntryPoint=L"main", pTargetProfile=L"vs_6_0", pArguments=0x0000555557073550, argCount=2 0x00000002, pDefines=0x00007fffffffd7f0, defineCount=0 0x00000000, pIncludeHandler=0x0000555557073570, ppResult=0x00007fffffffd320, ppDebugBlobName=0x0000000000000000, ppDebugBlob=0x0000000000000000) + 4288 at dxcompilerobj.cpp:1845
frame #41: 0x00007fffef56afa8 libdxcompiler.so hlsl::DxcCompilerAdapter::CompileWithDebug:`hlsl::DxcCompilerAdapter::CompileWithDebug(this=0x0000555557073cc0, pSource=0x0000555557073d70, pSourceName=L"crash.hlsl", pEntryPoint=L"main", pTargetProfile=L"vs_6_0", pArguments=0x0000555557073550, argCount=2 0x00000002, pDefines=0x00007fffffffd7f0, defineCount=0 0x00000000, pIncludeHandler=0x0000555557073570, ppResult=0x00007fffffffd320, ppDebugBlobName=0x0000000000000000, ppDebugBlob=0x0000000000000000) + 360 at dxcompilerobj.cpp:1748
frame #42: 0x00007fffef5724e8 libdxcompiler.so hlsl::DxcCompilerAdapter::Compile:`hlsl::DxcCompilerAdapter::Compile(this=0x0000555557073cc0, pSource=0x0000555557073d70, pSourceName=L"crash.hlsl", pEntryPoint=L"main", pTargetProfile=L"vs_6_0", pArguments=0x0000555557073550, argCount=2 0x00000002, pDefines=0x00007fffffffd7f0, defineCount=0 0x00000000, pIncludeHandler=0x0000555557073570, ppResult=0x00007fffffffd320) + 184 at dxcompileradapter.h:75
frame #43: 0x0000555555e15a30 dxc DxcContext::Compile:`DxcContext::Compile(this=0x00007fffffffd650) + 5344 at dxc.cpp:874
frame #44: 0x0000555555e1bce8 dxc dxc::main:`dxc::main(argc=4 0x00000004, argv_=0x00007fffffffe338) + 2744 at dxc.cpp:1502
frame #45: 0x0000555555e0ac52 dxc main:`main(argc=4 0x00000004, argv_=0x00007fffffffe338) + 34 at dxcmain.cpp:19
frame #46: 0x00007fffe6423d90 libc.so.6 __libc_start_call_main:`__libc_start_call_main(main=(dxc`main at dxcmain.cpp:18), argc=4 0x00000004, argv=0x00007fffffffe338) + 128 at libc_start_call_main.h:58
frame #47: 0x00007fffe6423e40 libc.so.6 __libc_start_main_impl:`__libc_start_main_impl(main=(dxc`main at dxcmain.cpp:18), argc=4 0x00000004, argv=0x00007fffffffe338, init=0x00007ffff7ffd040, fini=<unavailable>, rtld_fini=<unavailable>, stack_end=0x00007fffffffe328) + 128 at libc-start.c:392
frame #48: 0x0000555555de25e5 dxc _start:`_start + 37
The crash here is weird, it is crashing codegen-ing a flat conversion, but it should be (and is in the AST) a derived to base conversion.
Caused by: https://github.com/microsoft/DirectXShaderCompiler/pull/2312
Which treats derived-to-base as a flat conversion. That could cause all sorts of things to break.
btw what happens if you make the f() take an in or inout ?
Derived to base conversions are disallowed on out and inout parameters: https://godbolt.org/z/P1GP7sYns