[Mesa-dev] [PATCH] - fixing bug 83570...idiv by zero now returns zero instead of throwing a integer division by zero exception

Robert Conde rconde0001 at gmail.com
Thu Sep 11 18:47:22 PDT 2014


From: rconde <rconde01 at outlook.com>

---
 src/gallium/auxiliary/gallivm/lp_bld_tgsi_action.c | 22 ++++++++++++++++++++--
 src/gallium/auxiliary/tgsi/tgsi_exec.c             |  8 ++++----
 2 files changed, 24 insertions(+), 6 deletions(-)

diff --git a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_action.c b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_action.c
index b9546db..72be171 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_action.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_action.c
@@ -1248,8 +1248,26 @@ idiv_emit_cpu(
    struct lp_build_tgsi_context * bld_base,
    struct lp_build_emit_data * emit_data)
 {
-   emit_data->output[emit_data->chan] = lp_build_div(&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_div(&bld_base->uint_bld,
+                                      emit_data->args[0], divisor);
+                                      
+   LLVMValueRef not_div_mask = LLVMBuildNot(builder,
+                                            div_mask,"");
+                                          
+   /* idiv by zero is guaranteed to return 0x00000000 */
+   emit_data->output[emit_data->chan] = LLVMBuildAnd(builder,
+                                                     not_div_mask,
+                                                     result, "");
 }
 
 /* TGSI_OPCODE_INEG (CPU Only) */
diff --git a/src/gallium/auxiliary/tgsi/tgsi_exec.c b/src/gallium/auxiliary/tgsi/tgsi_exec.c
index 6dae379..7794801 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_exec.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_exec.c
@@ -3343,10 +3343,10 @@ micro_idiv(union tgsi_exec_channel *dst,
            const union tgsi_exec_channel *src0,
            const union tgsi_exec_channel *src1)
 {
-   dst->i[0] = src0->i[0] / src1->i[0];
-   dst->i[1] = src0->i[1] / src1->i[1];
-   dst->i[2] = src0->i[2] / src1->i[2];
-   dst->i[3] = src0->i[3] / src1->i[3];
+   dst->i[0] = src1->i[0] ? src0->i[0] / src1->i[0] : 0;
+   dst->i[1] = src1->i[1] ? src0->i[1] / src1->i[1] : 0;
+   dst->i[2] = src1->i[2] ? src0->i[2] / src1->i[2] : 0;
+   dst->i[3] = src1->i[3] ? src0->i[3] / src1->i[3] : 0;
 }
 
 static void
-- 
1.9.0.msysgit.0



More information about the mesa-dev mailing list