summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJay Kwak <82421531+jkwak-work@users.noreply.github.com>2024-06-10 13:29:02 -0700
committerGitHub <noreply@github.com>2024-06-10 13:29:02 -0700
commit72016f9201e4d7820f62e7ef78cee98ed1fc4da0 (patch)
treeb8d78b954791afd8ad409074cfd6cca96a6d6c79
parent712ce653d4c3d7284dd71389f31540d0da7f144e (diff)
Partial implementation of static_assert (#4294)
* Error out for types not supported by texture sample functions This commit prints errors with a new keyword, `static_assert`, when the given texture type is not supported for the target. * Moving the check to linkAndOptimizeIR after specialization is done * Remove unnecessary change * Adding test * Remove kIROp_StaticAssert once processed * Do not remove StaticAssert because it is needed for the next specialization * Remove after iteration of child is done --------- Co-authored-by: Yong He <yonghe@outlook.com>
-rw-r--r--source/slang/core.meta.slang3
-rw-r--r--source/slang/slang-diagnostic-defs.h5
-rw-r--r--source/slang/slang-emit-spirv.cpp1
-rw-r--r--source/slang/slang-emit.cpp49
-rw-r--r--source/slang/slang-ir-autodiff-fwd.cpp1
-rw-r--r--source/slang/slang-ir-inst-defs.h1
-rw-r--r--source/slang/slang-ir-insts.h5
-rw-r--r--tests/language-feature/static_assert.slang93
8 files changed, 158 insertions, 0 deletions
diff --git a/source/slang/core.meta.slang b/source/slang/core.meta.slang
index 272e95c85..fcb08984b 100644
--- a/source/slang/core.meta.slang
+++ b/source/slang/core.meta.slang
@@ -244,6 +244,9 @@ void __requirePrelude(constexpr String preludeText);
__intrinsic_op($(kIROp_RequireGLSLExtension))
void __requireGLSLExtension(constexpr String preludeText);
+__intrinsic_op($(kIROp_StaticAssert))
+void static_assert(constexpr bool condition, NativeString errorMessage);
+
/// Interface to denote types as differentiable.
/// Allows for user-specified differential types as
/// well as automatic generation, for when the associated type
diff --git a/source/slang/slang-diagnostic-defs.h b/source/slang/slang-diagnostic-defs.h
index 100543864..7fd31a46e 100644
--- a/source/slang/slang-diagnostic-defs.h
+++ b/source/slang/slang-diagnostic-defs.h
@@ -762,6 +762,11 @@ DIAGNOSTIC(41202, Error, notEqualBitCastSize, "invalid to bit_cast differently s
DIAGNOSTIC(41203, Warning, notEqualReinterpretCastSize, "reinterpret<> into not equally sized types: '$0' with size '$1' casted into '$2' with size '$3'")
DIAGNOSTIC(41300, Error, byteAddressBufferUnaligned, "invalid alignment `$0` specified for the byte address buffer resource with the element size of `$1`")
+
+DIAGNOSTIC(41400, Error, staticAssertionFailure, "static assertion failed, $0")
+DIAGNOSTIC(41401, Error, staticAssertionFailureWithoutMessage, "static assertion failed.")
+DIAGNOSTIC(41402, Error, staticAssertionConditionNotConstant, "condition for static assertion cannot be evaluated at the compile-time.")
+
//
// 5xxxx - Target code generation.
//
diff --git a/source/slang/slang-emit-spirv.cpp b/source/slang/slang-emit-spirv.cpp
index d7c6c64a5..1db323993 100644
--- a/source/slang/slang-emit-spirv.cpp
+++ b/source/slang/slang-emit-spirv.cpp
@@ -2632,6 +2632,7 @@ struct SPIRVEmitContext
}
case kIROp_Specialize:
case kIROp_MissingReturn:
+ case kIROp_StaticAssert:
break;
case kIROp_Var:
result = emitVar(parent, inst);
diff --git a/source/slang/slang-emit.cpp b/source/slang/slang-emit.cpp
index 02dab6dfa..da348fa64 100644
--- a/source/slang/slang-emit.cpp
+++ b/source/slang/slang-emit.cpp
@@ -362,6 +362,51 @@ void calcRequiredLoweringPassSet(RequiredLoweringPassSet& result, CodeGenContext
}
}
+bool checkStaticAssert(IRInst* inst, DiagnosticSink* sink)
+{
+ switch (inst->getOp())
+ {
+ case kIROp_StaticAssert:
+ {
+ IRInst* condi = inst->getOperand(0);
+ if (auto condiLit = as<IRBoolLit>(condi))
+ {
+ if (!condiLit->getValue())
+ {
+ IRInst* msg = inst->getOperand(1);
+ if (auto msgLit = as<IRStringLit>(msg))
+ {
+ sink->diagnose(inst, Diagnostics::staticAssertionFailure, msgLit->getStringSlice());
+ }
+ else
+ {
+ sink->diagnose(inst, Diagnostics::staticAssertionFailureWithoutMessage);
+ }
+ }
+ }
+ else
+ {
+ sink->diagnose(condi, Diagnostics::staticAssertionConditionNotConstant);
+ }
+
+ return true;
+ }
+ }
+
+ List<IRInst*> removeList;
+ for (auto child : inst->getChildren())
+ {
+ if (checkStaticAssert(child, sink))
+ removeList.add(child);
+ }
+ for (auto child : removeList)
+ {
+ child->removeAndDeallocate();
+ }
+
+ return false;
+}
+
Result linkAndOptimizeIR(
CodeGenContext* codeGenContext,
LinkingAndOptimizationOptions const& options,
@@ -881,6 +926,10 @@ Result linkAndOptimizeIR(
validateIRModuleIfEnabled(codeGenContext, irModule);
+ // Process `static_assert` after the specialization is done.
+ // Some information for `static_assert` is available only after the specialization.
+ checkStaticAssert(irModule->getModuleInst(), sink);
+
// For HLSL (and fxc/dxc) only, we need to "wrap" any
// structured buffers defined over matrix types so
// that they instead use an intermediate `struct`.
diff --git a/source/slang/slang-ir-autodiff-fwd.cpp b/source/slang/slang-ir-autodiff-fwd.cpp
index 299f4655b..492ff0ca1 100644
--- a/source/slang/slang-ir-autodiff-fwd.cpp
+++ b/source/slang/slang-ir-autodiff-fwd.cpp
@@ -1911,6 +1911,7 @@ InstPair ForwardDiffTranscriber::transcribeInstImpl(IRBuilder* builder, IRInst*
case kIROp_RWStructuredBufferGetElementPtr:
case kIROp_NonUniformResourceIndex:
case kIROp_IsType:
+ case kIROp_StaticAssert:
case kIROp_ImageSubscript:
case kIROp_ImageLoad:
case kIROp_ImageStore:
diff --git a/source/slang/slang-ir-inst-defs.h b/source/slang/slang-ir-inst-defs.h
index 37e3d2064..74990ed55 100644
--- a/source/slang/slang-ir-inst-defs.h
+++ b/source/slang/slang-ir-inst-defs.h
@@ -600,6 +600,7 @@ INST(discard, discard, 0, 0)
INST(RequirePrelude, RequirePrelude, 1, 0)
INST(RequireGLSLExtension, RequireGLSLExtension, 1, 0)
INST(RequireComputeDerivative, RequireComputeDerivative, 0, 0)
+INST(StaticAssert, StaticAssert, 2, 0)
// TODO: We should consider splitting the basic arithmetic/comparison
// ops into cases for signed integers, unsigned integers, and floating-point
diff --git a/source/slang/slang-ir-insts.h b/source/slang/slang-ir-insts.h
index 301604bf3..9e377fe73 100644
--- a/source/slang/slang-ir-insts.h
+++ b/source/slang/slang-ir-insts.h
@@ -3249,6 +3249,11 @@ struct IRRequireComputeDerivative : IRInst
IR_LEAF_ISA(RequireComputeDerivative)
};
+struct IRStaticAssert : IRInst
+{
+ IR_LEAF_ISA(StaticAssert)
+};
+
struct IRBuilderSourceLocRAII;
struct IRBuilder
diff --git a/tests/language-feature/static_assert.slang b/tests/language-feature/static_assert.slang
new file mode 100644
index 000000000..55bfa0abb
--- /dev/null
+++ b/tests/language-feature/static_assert.slang
@@ -0,0 +1,93 @@
+//TEST:SIMPLE(filecheck=CHK):-target hlsl -stage compute -entry computeMain
+//TEST:SIMPLE(filecheck=CHK):-target glsl -stage compute -entry computeMain
+//TEST:SIMPLE(filecheck=CHK):-target spirv -stage compute -entry computeMain
+//TEST:SIMPLE(filecheck=HLSL):-target hlsl -stage compute -entry computeMain
+//TEST:SIMPLE(filecheck=GLSL):-target glsl -stage compute -entry computeMain
+//TEST:SIMPLE(filecheck=SPV):-target spirv -stage compute -entry computeMain
+
+// TODO: requires changes in parser
+//static_assert(true, "PASS_global");
+//static_assert(false, "FAIL_global");
+
+__generic<T:IArithmetic>
+void TEST_specialize()
+{
+ static_assert(true, "TEST_specialize true");
+ static_assert(T is float, "TEST_specialize T_is_float");
+ static_assert(T is int, "TEST_specialize T_is_int");
+}
+
+void TEST_target_switch()
+{
+ static_assert(false, "TEST_target_switch all");
+ __target_switch
+ {
+ case hlsl:
+ static_assert(false, "TEST_target_switch hlsl");
+ return;
+ case glsl:
+ static_assert(false, "TEST_target_switch glsl");
+ return;
+ default:
+ static_assert(false, "TEST_target_switch default");
+ return;
+ }
+}
+
+__generic<T:IArithmetic>
+struct MyType
+{
+ // TODO: requires changes in parser
+ //static_assert(true, "PASS_struct");
+ //static_assert(false, "FAIL_struct");
+
+ __init()
+ {
+ static_assert(true, "MyType init true");
+ static_assert(false, "MyType init false");
+ }
+};
+
+__generic<T:IFloat>
+extension MyType<T>
+{
+};
+
+[numthreads(1,1,1)]
+void computeMain(int3 dispatchThreadID: SV_DispatchThreadID)
+{
+ //CHK-NOT:error {{.*}} TEST_specialize
+ //CHK: error {{.*}} TEST_specialize T_is_int
+ //CHK-NOT:error {{.*}} TEST_specialize
+ TEST_specialize<float>();
+
+ //CHK-NOT:error {{.*}} TEST_specialize
+ //CHK: error 41400: {{.*}} TEST_specialize T_is_float
+ //CHK-NOT:error {{.*}} TEST_specialize
+ TEST_specialize<int>();
+
+ //HLSL: error {{.*}} TEST_target_switch all
+ //HLSL: error {{.*}} TEST_target_switch hlsl
+ //HLSL-NOT: error {{.*}} TEST_target_switch glsl
+ //HLSL-NOT: error {{.*}} TEST_target_switch default
+ //
+ //GLSL: error {{.*}} TEST_target_switch all
+ //GLSL-NOT: error {{.*}} TEST_target_switch hlsl
+ //GLSL: error {{.*}} TEST_target_switch glsl
+ //GLSL-NOT: error {{.*}} TEST_target_switch default
+ //
+ //SPV: error {{.*}} TEST_target_switch all
+ //SPV-NOT: error {{.*}} TEST_target_switch hlsl
+ //SPV-NOT: error {{.*}} TEST_target_switch glsl
+ //SPV: error {{.*}} TEST_target_switch default
+ //
+ TEST_target_switch();
+
+ //CHK-NOT: error {{.*}} MyType init true
+ //CHK: error {{.*}} MyType init false
+ MyType<float> obj;
+
+ //CHK: ([[#@LINE+1]]): error
+ static_assert(dispatchThreadID.x == 0, "not constant");
+}
+