summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
authorEllie Hermaszewska <ellieh@nvidia.com>2023-05-05 03:46:42 +0800
committerGitHub <noreply@github.com>2023-05-04 12:46:42 -0700
commitab3ac985479132856613d6dcc8b43f4a4ef8c6b7 (patch)
treee4e911d10b8ec2866e7e408f9a10b51d743ee675 /source
parentc0b6f59a6920a9efbb4ecc3b622529db484c64ef (diff)
Add SLANG_ASSUME and use it in release asserts (#2859)
* Remove UNREACHABLE * formatting * Remove unused SLANG_EXPECT macros * Add SLANG_ASSUME and use it in release asserts * Reassure GCC that we are using memcpy responsibly --------- Co-authored-by: Yong He <yonghe@outlook.com>
Diffstat (limited to 'source')
-rw-r--r--source/core/slang-common.h31
-rw-r--r--source/core/slang-io.cpp8
-rw-r--r--source/slang/slang-emit-hlsl.cpp2
-rw-r--r--source/slang/slang-ir-glsl-legalize.cpp12
4 files changed, 35 insertions, 18 deletions
diff --git a/source/core/slang-common.h b/source/core/slang-common.h
index cd1490a20..5cf0432f2 100644
--- a/source/core/slang-common.h
+++ b/source/core/slang-common.h
@@ -76,28 +76,43 @@ namespace Slang
template <typename T>
SLANG_FORCE_INLINE T* clone(IClonable* clonable) { return (T*)clonable->clone(T::getTypeGuid()); }
+}
// TODO: Shouldn't these be SLANG_ prefixed?
#ifdef _MSC_VER
#define UNREACHABLE_RETURN(x)
-#define UNREACHABLE(x)
#else
#define UNREACHABLE_RETURN(x) return x;
-#define UNREACHABLE(x) x;
#endif
-}
+//
+// Use `SLANG_ASSUME(myBoolExpression);` to inform the compiler that the condition is true.
+// Do not rely on side effects of the condition being performed.
+//
+#if defined(__cpp_assume)
+# define SLANG_ASSUME(X) [[assume(X)]]
+#elif SLANG_GCC
+# define SLANG_ASSUME(X) do{if(!(X)) __builtin_unreachable();} while(0)
+#elif SLANG_CLANG
+# define SLANG_ASSUME(X) __builtin_assume(X)
+#elif SLANG_VC
+# define SLANG_ASSUME(X) __assume(X)
+#else
+ [[noreturn]] inline void invokeUndefinedBehaviour() {}
+# define SLANG_ASSUME(X) do{if(!(X)) invokeUndefinedBehaviour();} while(0)
+#endif
+//
+// Assertions abort in debug builds, but inform the compiler of true
+// assumptions in release builds
+//
#ifdef _DEBUG
-#define SLANG_EXPECT(VALUE, MSG) if(VALUE) {} else SLANG_ASSERT_FAILURE(MSG)
-#define SLANG_ASSERT(VALUE) SLANG_EXPECT(VALUE, #VALUE)
+#define SLANG_ASSERT(VALUE) do{if(!(VALUE)) SLANG_ASSERT_FAILURE(#VALUE);} while(0)
#else
-#define SLANG_EXPECT(VALUE, MSG) do {} while(0)
-#define SLANG_ASSERT(VALUE) do {} while(0)
+#define SLANG_ASSERT(VALUE) SLANG_ASSUME(VALUE)
#endif
#define SLANG_RELEASE_ASSERT(VALUE) if(VALUE) {} else SLANG_ASSERT_FAILURE(#VALUE)
-#define SLANG_RELEASE_EXPECT(VALUE, WHAT) if(VALUE) {} else SLANG_UNEXPECTED(WHAT)
template<typename T> void slang_use_obj(T&) {}
diff --git a/source/core/slang-io.cpp b/source/core/slang-io.cpp
index 81f0cbf87..8a2243b15 100644
--- a/source/core/slang-io.cpp
+++ b/source/core/slang-io.cpp
@@ -124,9 +124,11 @@ namespace Slang
builder << "/tmp/" << inPrefix << "-XXXXXX";
List<char> buffer;
- buffer.setCount(builder.getLength() + 1);
- ::memcpy(buffer.getBuffer(), builder.getBuffer(), builder.getLength());
- buffer[builder.getLength()] = 0;
+ auto copySize = builder.getLength();
+ buffer.setCount(copySize + 1);
+ SLANG_ASSERT(copySize < PTRDIFF_MAX); // Shhh gcc, it's ok, we're not copying 9000 Petabytes
+ ::memcpy(buffer.getBuffer(), builder.getBuffer(), copySize);
+ buffer[copySize] = 0;
int handle = mkstemp(buffer.getBuffer());
if (handle == -1)
diff --git a/source/slang/slang-emit-hlsl.cpp b/source/slang/slang-emit-hlsl.cpp
index 434f0803e..96b751789 100644
--- a/source/slang/slang-emit-hlsl.cpp
+++ b/source/slang/slang-emit-hlsl.cpp
@@ -1168,7 +1168,7 @@ void HLSLSourceEmitter::emitMeshOutputModifiersImpl(IRInst* varInst)
: as<IRIndicesDecoration>(modifier) ? "indices "
: as<IRPrimitivesDecoration>(modifier) ? "primitives "
: nullptr;
- SLANG_EXPECT(s, "Unhandled type of mesh output decoration");
+ SLANG_ASSERT(s && "Unhandled type of mesh output decoration");
m_writer->emit(s);
}
}
diff --git a/source/slang/slang-ir-glsl-legalize.cpp b/source/slang/slang-ir-glsl-legalize.cpp
index 8181deb1b..f6df7aa23 100644
--- a/source/slang/slang-ir-glsl-legalize.cpp
+++ b/source/slang/slang-ir-glsl-legalize.cpp
@@ -952,7 +952,7 @@ ScalarizedVal createSimpleGLSLGlobalVarying(
// It's legal to declare these as unsized arrays, but by sizing
// them by the (max) max size GLSL allows us to index into them
// with variable index.
- SLANG_EXPECT(dd->elementCount, "Mesh output declarator didn't specify element count");
+ SLANG_ASSERT(dd->elementCount && "Mesh output declarator didn't specify element count");
auto arrayType = builder->getArrayType(type, dd->elementCount);
IRArrayTypeLayout::Builder arrayTypeLayoutBuilder(builder, typeLayout);
@@ -1737,7 +1737,7 @@ void legalizeMeshOutputParam(
{
auto builder = context->getBuilder();
auto stage = context->getStage();
- SLANG_EXPECT(stage == Stage::Mesh, "legalizing mesh output, but we're not a mesh shader");
+ SLANG_ASSERT(stage == Stage::Mesh && "legalizing mesh output, but we're not a mesh shader");
IRBuilderInsertLocScope locScope{builder};
builder->setInsertInto(func);
@@ -1814,7 +1814,7 @@ void legalizeMeshOutputParam(
traverseUsers(g, [&](IRInst* u)
{
auto l = as<IRLoad>(u);
- SLANG_EXPECT(l, "Mesh Output sentinel parameter wasn't used in a load");
+ SLANG_ASSERT(l && "Mesh Output sentinel parameter wasn't used in a load");
std::function<void(ScalarizedVal&, IRInst*)> assignUses =
[&](ScalarizedVal& d, IRInst* a)
@@ -1838,7 +1838,7 @@ void legalizeMeshOutputParam(
if(auto m = as<IRFieldAddress>(s))
{
auto key = as<IRStructKey>(m->getField());
- SLANG_EXPECT(key, "Result of getField wasn't a struct key");
+ SLANG_ASSERT(key && "Result of getField wasn't a struct key");
auto d_ = extractField(builder, d, kMaxUInt, key);
assignUses(d_, m);
@@ -1880,7 +1880,7 @@ void legalizeMeshOutputParam(
// best we can hope for without going and
// specializing foo.
auto ptr = as<IRPtrTypeBase>(a->getFullType());
- SLANG_EXPECT(ptr, "Mesh output parameter was passed by value");
+ SLANG_ASSERT(ptr && "Mesh output parameter was passed by value");
auto t = ptr->getValueType();
auto tmp = builder->emitVar(t);
for(UInt i = 0; i < c->getOperandCount(); i++)
@@ -2045,7 +2045,7 @@ void legalizeMeshOutputParam(
traverseUsers(builtin.param, [&](IRInst* u)
{
auto p = as<IRGetElementPtr>(u);
- SLANG_EXPECT(p, "Mesh Output sentinel parameter wasn't used as an array");
+ SLANG_ASSERT(p && "Mesh Output sentinel parameter wasn't used as an array");
IRBuilderInsertLocScope locScope{builder};
builder->setInsertBefore(p);