diff --git a/include/slang.h b/include/slang.h index 356a2f496e..eb43c409a5 100644 --- a/include/slang.h +++ b/include/slang.h @@ -1007,6 +1007,10 @@ typedef uint32_t SlangSizeT; EmitSpirvMethod, // enum SlangEmitSpirvMethod EmitReflectionJSON, // bool + + SkipMatrixDimensionValidation, // bool, don't validate that matrix dimensions are > 1 when + // set + CountOf, }; diff --git a/source/slang-record-replay/util/emum-to-string.h b/source/slang-record-replay/util/emum-to-string.h index b197821269..c4428d5164 100644 --- a/source/slang-record-replay/util/emum-to-string.h +++ b/source/slang-record-replay/util/emum-to-string.h @@ -233,6 +233,7 @@ static Slang::String CompilerOptionNameToString(const slang::CompilerOptionName CASE(VulkanBindShiftAll); CASE(GenerateWholeProgram); CASE(UseUpToDateBinaryModule); + CASE(SkipMatrixDimensionValidation); CASE(CountOf); default: Slang::StringBuilder str; diff --git a/source/slang/slang-compiler.cpp b/source/slang/slang-compiler.cpp index c0c2c09c52..2157dd3375 100644 --- a/source/slang/slang-compiler.cpp +++ b/source/slang/slang-compiler.cpp @@ -2625,6 +2625,12 @@ bool CodeGenContext::shouldValidateIR() return getTargetProgram()->getOptionSet().getBoolOption(CompilerOptionName::ValidateIr); } +bool CodeGenContext::shouldSkipMatrixDimensionValidation() +{ + return getTargetProgram()->getOptionSet().getBoolOption( + CompilerOptionName::SkipMatrixDimensionValidation); +} + bool CodeGenContext::shouldSkipSPIRVValidation() { return getTargetProgram()->getOptionSet().getBoolOption( diff --git a/source/slang/slang-compiler.h b/source/slang/slang-compiler.h index cc4fc8dccd..d600b2320a 100644 --- a/source/slang/slang-compiler.h +++ b/source/slang/slang-compiler.h @@ -2856,6 +2856,7 @@ struct CodeGenContext IRDumpOptions getIRDumpOptions(); bool shouldValidateIR(); + bool shouldSkipMatrixDimensionValidation(); bool shouldDumpIR(); bool shouldReportCheckpointIntermediates(); diff --git a/source/slang/slang-diagnostic-defs.h b/source/slang/slang-diagnostic-defs.h index 821a895bc7..469e720ec7 100644 --- a/source/slang/slang-diagnostic-defs.h +++ b/source/slang/slang-diagnostic-defs.h @@ -1658,6 +1658,12 @@ DIAGNOSTIC( overloadedParameterToHigherOrderFunction, "passing overloaded functions to higher order functions is not supported") +DIAGNOSTIC( + 39999, + Error, + matrixColumnOrRowCountIsOne, + "matrix of type '$0' has column or row count of 1") + // 38xxx DIAGNOSTIC( diff --git a/source/slang/slang-emit.cpp b/source/slang/slang-emit.cpp index ee25822670..7d2666c87a 100644 --- a/source/slang/slang-emit.cpp +++ b/source/slang/slang-emit.cpp @@ -555,6 +555,24 @@ static void unexportNonEmbeddableIR(CodeGenTarget target, IRModule* irModule) } } +static void validateMatrixDimensions(DiagnosticSink* sink, IRInst* inst) +{ + if (auto matrixType = as(inst->getDataType())) + { + auto colCount = as(matrixType->getColumnCount()); + auto rowCount = as(matrixType->getRowCount()); + + if ((rowCount && (rowCount->getValue() == 1)) || (colCount && (colCount->getValue() == 1))) + { + sink->diagnose(inst->sourceLoc, Diagnostics::matrixColumnOrRowCountIsOne, matrixType); + } + } + for (auto child : inst->getModifiableChildren()) + { + validateMatrixDimensions(sink, child); + } +}; + Result linkAndOptimizeIR( CodeGenContext* codeGenContext, LinkingAndOptimizationOptions const& options, @@ -1504,6 +1522,10 @@ Result linkAndOptimizeIR( #endif validateIRModuleIfEnabled(codeGenContext, irModule); + // Make sure there are no matrices with 1 row/column + if (!codeGenContext->shouldSkipMatrixDimensionValidation()) + validateMatrixDimensions(sink, irModule->getModuleInst()); + // The resource-based specialization pass above // may create specialized versions of functions, but // it does not try to completely eliminate the original diff --git a/source/slang/slang-options.cpp b/source/slang/slang-options.cpp index a0e8515ebf..4135a386d6 100644 --- a/source/slang/slang-options.cpp +++ b/source/slang/slang-options.cpp @@ -801,6 +801,10 @@ void initCommandOptions(CommandOptions& options) "Serialize the IR between front-end and back-end."}, {OptionKind::SkipCodeGen, "-skip-codegen", nullptr, "Skip the code generation phase."}, {OptionKind::ValidateIr, "-validate-ir", nullptr, "Validate the IR between the phases."}, + {OptionKind::SkipMatrixDimensionValidation, + "-skip-matrix-dimension-validation", + nullptr, + "Skip matrix dimension validation."}, {OptionKind::VerbosePaths, "-verbose-paths", nullptr, @@ -2150,6 +2154,7 @@ SlangResult OptionsParser::_parse(int argc, char const* const* argv) case OptionKind::LoopInversion: case OptionKind::UnscopedEnum: case OptionKind::PreserveParameters: + case OptionKind::SkipMatrixDimensionValidation: linkage->m_optionSet.set(optionKind, true); break; case OptionKind::MatrixLayoutRow: