diff options
| author | Ellie Hermaszewska <ellieh@nvidia.com> | 2023-05-05 03:46:42 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-05-04 12:46:42 -0700 |
| commit | ab3ac985479132856613d6dcc8b43f4a4ef8c6b7 (patch) | |
| tree | e4e911d10b8ec2866e7e408f9a10b51d743ee675 /source | |
| parent | c0b6f59a6920a9efbb4ecc3b622529db484c64ef (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.h | 31 | ||||
| -rw-r--r-- | source/core/slang-io.cpp | 8 | ||||
| -rw-r--r-- | source/slang/slang-emit-hlsl.cpp | 2 | ||||
| -rw-r--r-- | source/slang/slang-ir-glsl-legalize.cpp | 12 |
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); |
