summaryrefslogtreecommitdiffstats
path: root/src/compiler/spirv/vtn_private.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler/spirv/vtn_private.h')
-rw-r--r--src/compiler/spirv/vtn_private.h47
1 files changed, 47 insertions, 0 deletions
diff --git a/src/compiler/spirv/vtn_private.h b/src/compiler/spirv/vtn_private.h
index cac4d45864b..d07f6a2beb2 100644
--- a/src/compiler/spirv/vtn_private.h
+++ b/src/compiler/spirv/vtn_private.h
@@ -28,6 +28,8 @@
#ifndef _VTN_PRIVATE_H_
#define _VTN_PRIVATE_H_
+#include <setjmp.h>
+
#include "nir/nir.h"
#include "nir/nir_builder.h"
#include "util/u_dynarray.h"
@@ -49,6 +51,48 @@ void _vtn_warn(struct vtn_builder *b, const char *file, unsigned line,
const char *fmt, ...) PRINTFLIKE(4, 5);
#define vtn_warn(...) _vtn_warn(b, __FILE__, __LINE__, __VA_ARGS__)
+/** Fail SPIR-V parsing
+ *
+ * This function logs an error and then bails out of the shader compile using
+ * longjmp. This being safe relies on two things:
+ *
+ * 1) We must guarantee that setjmp is called after allocating the builder
+ * and setting up b->debug (so that logging works) but before before any
+ * errors have a chance to occur.
+ *
+ * 2) While doing the SPIR-V -> NIR conversion, we need to be careful to
+ * ensure that all heap allocations happen through ralloc and are parented
+ * to the builder. This way they will get properly cleaned up on error.
+ *
+ * 3) We must ensure that _vtn_fail is never called while a mutex lock or a
+ * reference to any other resource is held with the exception of ralloc
+ * objects which are parented to the builder.
+ *
+ * So long as these two things continue to hold, we can easily longjmp back to
+ * spirv_to_nir(), clean up the builder, and return NULL.
+ */
+void _vtn_fail(struct vtn_builder *b, const char *file, unsigned line,
+ const char *fmt, ...) NORETURN PRINTFLIKE(4, 5);
+#define vtn_fail(...) _vtn_fail(b, __FILE__, __LINE__, __VA_ARGS__)
+
+/** Fail if the given expression evaluates to true */
+#define vtn_fail_if(expr, ...) \
+ do { \
+ if (unlikely(expr)) \
+ vtn_fail(__VA_ARGS__); \
+ } while (0)
+
+/** Assert that a condition is true and, if it isn't, vtn_fail
+ *
+ * This macro is transitional only and should not be used in new code. Use
+ * vtn_fail_if and provide a real message instead.
+ */
+#define vtn_assert(expr) \
+ do { \
+ if (!likely(expr)) \
+ vtn_fail("%s", #expr); \
+ } while (0)
+
enum vtn_value_type {
vtn_value_type_invalid = 0,
vtn_value_type_undef,
@@ -478,6 +522,9 @@ struct vtn_decoration {
struct vtn_builder {
nir_builder nb;
+ /* Used by vtn_fail to jump back to the beginning of SPIR-V compilation */
+ jmp_buf fail_jump;
+
const uint32_t *spirv;
nir_shader *shader;