diff options
| author | kaizhangNV <149626564+kaizhangNV@users.noreply.github.com> | 2025-02-12 15:37:05 -0600 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-02-12 13:37:05 -0800 |
| commit | 3f102afe1038882f336dc052a9954811150fa700 (patch) | |
| tree | 9411909bf649eed9724d14226ed07890a0671329 /source | |
| parent | 0fee8c16e25521d13b50427ac6bf87d7f3419b9c (diff) | |
Fix crash when handling uninitialized resource type (#6338)
* Fix crash when handling uninitialized resource type
close #6328.
When declare a var with struct type, if the struct has a resource
type field and it doesn't provide explicit constructor, because
slang won't implicit construct such variable at declare site if user
doesn't explicitly call the initializer list, we should report the
resource type field uninitialized as an error to prevent future possible
crash when legalize any use of such variable.
Diffstat (limited to 'source')
| -rw-r--r-- | source/slang/slang-diagnostic-defs.h | 2 | ||||
| -rw-r--r-- | source/slang/slang-ir-legalize-types.cpp | 54 | ||||
| -rw-r--r-- | source/slang/slang-legalize-types.cpp | 58 | ||||
| -rw-r--r-- | source/slang/slang-legalize-types.h | 5 |
4 files changed, 100 insertions, 19 deletions
diff --git a/source/slang/slang-diagnostic-defs.h b/source/slang/slang-diagnostic-defs.h index acb9beb94..4f72332ef 100644 --- a/source/slang/slang-diagnostic-defs.h +++ b/source/slang/slang-diagnostic-defs.h @@ -2551,6 +2551,8 @@ DIAGNOSTIC( attemptToQuerySizeOfUnsizedArray, "cannot obtain the size of an unsized array.") +DIAGNOSTIC(56003, Fatal, useOfUninitializedOpaqueHandle, "use of uninitialized opaque handle '$0'.") + // Metal DIAGNOSTIC( 56100, diff --git a/source/slang/slang-ir-legalize-types.cpp b/source/slang/slang-ir-legalize-types.cpp index a3e47fd55..172171912 100644 --- a/source/slang/slang-ir-legalize-types.cpp +++ b/source/slang/slang-ir-legalize-types.cpp @@ -91,7 +91,10 @@ LegalVal LegalVal::wrappedBuffer(LegalVal const& baseVal, LegalElementWrapping c // -IRTypeLegalizationContext::IRTypeLegalizationContext(TargetProgram* target, IRModule* inModule) +IRTypeLegalizationContext::IRTypeLegalizationContext( + TargetProgram* target, + IRModule* inModule, + DiagnosticSink* sink) { targetProgram = target; @@ -100,6 +103,8 @@ IRTypeLegalizationContext::IRTypeLegalizationContext(TargetProgram* target, IRMo builderStorage = IRBuilder(inModule); builder = &builderStorage; + + m_sink = sink; } static void registerLegalizedValue( @@ -2046,6 +2051,23 @@ static LegalVal coerceToLegalType(IRTypeLegalizationContext* context, LegalType } } +static LegalVal legalizeUndefined(IRTypeLegalizationContext* context, IRInst* inst) +{ + List<IRType*> opaqueTypes; + if (isOpaqueType(inst->getFullType(), opaqueTypes)) + { + auto opaqueType = opaqueTypes[0]; + auto containerType = opaqueTypes.getCount() > 1 ? opaqueTypes[1] : opaqueType; + SourceLoc loc = findBestSourceLocFromUses(inst); + + if (!loc.isValid()) + loc = getDiagnosticPos(containerType); + + context->m_sink->diagnose(loc, Diagnostics::useOfUninitializedOpaqueHandle, opaqueType); + } + return LegalVal(); +} + static LegalVal legalizeInst( IRTypeLegalizationContext* context, IRInst* inst, @@ -2122,7 +2144,7 @@ static LegalVal legalizeInst( result = legalizePrintf(context, args); break; case kIROp_undefined: - return LegalVal(); + return legalizeUndefined(context, inst); case kIROp_GpuForeach: // This case should only happen when compiling for a target that does not support // GpuForeach @@ -4015,8 +4037,8 @@ static void legalizeTypes(IRTypeLegalizationContext* context) // struct IRResourceTypeLegalizationContext : IRTypeLegalizationContext { - IRResourceTypeLegalizationContext(TargetProgram* target, IRModule* module) - : IRTypeLegalizationContext(target, module) + IRResourceTypeLegalizationContext(TargetProgram* target, IRModule* module, DiagnosticSink* sink) + : IRTypeLegalizationContext(target, module, sink) { } @@ -4046,8 +4068,11 @@ struct IRResourceTypeLegalizationContext : IRTypeLegalizationContext // struct IRExistentialTypeLegalizationContext : IRTypeLegalizationContext { - IRExistentialTypeLegalizationContext(TargetProgram* target, IRModule* module) - : IRTypeLegalizationContext(target, module) + IRExistentialTypeLegalizationContext( + TargetProgram* target, + IRModule* module, + DiagnosticSink* sink) + : IRTypeLegalizationContext(target, module, sink) { } @@ -4087,8 +4112,8 @@ struct IRExistentialTypeLegalizationContext : IRTypeLegalizationContext // a public function signature. struct IREmptyTypeLegalizationContext : IRTypeLegalizationContext { - IREmptyTypeLegalizationContext(TargetProgram* target, IRModule* module) - : IRTypeLegalizationContext(target, module) + IREmptyTypeLegalizationContext(TargetProgram* target, IRModule* module, DiagnosticSink* sink) + : IRTypeLegalizationContext(target, module, sink) { } @@ -4129,9 +4154,7 @@ void legalizeResourceTypes(TargetProgram* target, IRModule* module, DiagnosticSi { SLANG_PROFILE; - SLANG_UNUSED(sink); - - IRResourceTypeLegalizationContext context(target, module); + IRResourceTypeLegalizationContext context(target, module, sink); legalizeTypes(&context); } @@ -4139,18 +4162,13 @@ void legalizeExistentialTypeLayout(TargetProgram* target, IRModule* module, Diag { SLANG_PROFILE; - SLANG_UNUSED(module); - SLANG_UNUSED(sink); - - IRExistentialTypeLegalizationContext context(target, module); + IRExistentialTypeLegalizationContext context(target, module, sink); legalizeTypes(&context); } void legalizeEmptyTypes(TargetProgram* target, IRModule* module, DiagnosticSink* sink) { - SLANG_UNUSED(sink); - - IREmptyTypeLegalizationContext context(target, module); + IREmptyTypeLegalizationContext context(target, module, sink); legalizeTypes(&context); } diff --git a/source/slang/slang-legalize-types.cpp b/source/slang/slang-legalize-types.cpp index 7695ba385..7d107bbce 100644 --- a/source/slang/slang-legalize-types.cpp +++ b/source/slang/slang-legalize-types.cpp @@ -198,6 +198,64 @@ bool isResourceType(IRType* type) return false; } +bool isOpaqueType(IRType* type, List<IRType*>& opaqueTypes) +{ + if (isResourceType(type)) + { + opaqueTypes.add(type); + return true; + } + + if (auto structType = as<IRStructType>(type)) + { + for (auto field : structType->getFields()) + { + if (isOpaqueType(field->getFieldType(), opaqueTypes)) + { + opaqueTypes.add(type); + return true; + } + } + } + + if (auto arrayType = as<IRArrayTypeBase>(type)) + { + if (isOpaqueType(arrayType->getElementType(), opaqueTypes)) + { + opaqueTypes.add(type); + return true; + } + } + + if (auto tupleType = as<IRTupleTypeBase>(type)) + { + for (UInt i = 0; i < tupleType->getOperandCount(); i++) + { + if (auto elementType = as<IRType>(tupleType->getOperand(i))) + { + if (isOpaqueType(elementType, opaqueTypes)) + { + opaqueTypes.add(type); + return true; + } + } + } + } + + return false; +} + +SourceLoc findBestSourceLocFromUses(IRInst* inst) +{ + for (auto use = inst->firstUse; use; use = use->nextUse) + { + auto user = use->getUser(); + if (user->sourceLoc.isValid()) + return user->sourceLoc; + } + + return inst->sourceLoc; +} // Helper wrapper function around isResourceType that checks if the given // type is a pointer to a resource type or a physical storage buffer. bool isPointerToResourceType(IRType* type) diff --git a/source/slang/slang-legalize-types.h b/source/slang/slang-legalize-types.h index eaee373b2..17498ce08 100644 --- a/source/slang/slang-legalize-types.h +++ b/source/slang/slang-legalize-types.h @@ -592,8 +592,9 @@ struct IRTypeLegalizationContext IRBuilder* builder; TargetProgram* targetProgram; IRBuilder builderStorage; + DiagnosticSink* m_sink; - IRTypeLegalizationContext(TargetProgram* target, IRModule* inModule); + IRTypeLegalizationContext(TargetProgram* target, IRModule* inModule, DiagnosticSink* sink); // When inserting new globals, put them before this one. IRInst* insertBeforeGlobal = nullptr; @@ -702,7 +703,9 @@ void legalizeEmptyTypes(TargetProgram* target, IRModule* module, DiagnosticSink* bool isResourceType(IRType* type); +bool isOpaqueType(IRType* type, List<IRType*>& opaqueTypes); +SourceLoc findBestSourceLocFromUses(IRInst* inst); } // namespace Slang #endif |
