[Mesa-dev] [PATCH] avoid crashing in mod by 0 with llvmpipe

Jeff Muizelaar jmuizelaar at mozilla.com
Fri Jan 15 11:13:34 PST 2016


This adds code that is basically the same as the code in smod, div and idiv.
However, unlike idiv we return -1.

diff --git a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_action.c
b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_action.c
index 0ad78b0..d17ef31 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_action.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_action.c
@@ -1524,18 +1524,32 @@ min_emit_cpu(

 /* TGSI_OPCODE_MOD (CPU Only) */
 static void
 mod_emit_cpu(
    const struct lp_build_tgsi_action * action,
    struct lp_build_tgsi_context * bld_base,
    struct lp_build_emit_data * emit_data)
 {
-   emit_data->output[emit_data->chan] = lp_build_mod(&bld_base->int_bld,
-                                   emit_data->args[0], emit_data->args[1]);
+   LLVMBuilderRef builder = bld_base->base.gallivm->builder;
+   LLVMValueRef div_mask = lp_build_cmp(&bld_base->uint_bld,
+                    PIPE_FUNC_EQUAL, emit_data->args[1],
+                    bld_base->uint_bld.zero);
+   /* We want to make sure that we never divide/mod by zero to not
+    * generate sigfpe. We don't want to crash just because the
+    * shader is doing something weird. */
+   LLVMValueRef divisor = LLVMBuildOr(builder,
+                      div_mask,
+                      emit_data->args[1], "");
+   LLVMValueRef result = lp_build_mod(&bld_base->int_bld,
+                      emit_data->args[0], divisor);
+   /* umod by zero is guaranteed to return 0xffffffff */
+   emit_data->output[emit_data->chan] = LLVMBuildOr(builder,
+                            div_mask,
+                            result, "");
 }

 /* TGSI_OPCODE_NOT */
 static void
 not_emit_cpu(
    const struct lp_build_tgsi_action * action,
    struct lp_build_tgsi_context * bld_base,
    struct lp_build_emit_data * emit_data)


More information about the mesa-dev mailing list