From a0f1a5fa051786c16de6f0062771051f8565daec Mon Sep 17 00:00:00 2001 From: Samuel Pitoiset Date: Tue, 10 Dec 2019 17:46:26 +0100 Subject: [PATCH] ac/nir: fix out-of-bound access when loading constants from global Global load/store instructions can't know if the offset is out-of-bound because they don't use descriptors (no range). Fix this by clamping the offset for arrays that are indexed with a non-constant offset that's greater or equal to the array size. This fixes VM faults and GPU hangs with Dead Rising 4. Closes: https://gitlab.freedesktop.org/mesa/mesa/issues/2148 Fixes: 71a67942003 ("ac/nir: Enable nir_opt_large_constants") Signed-off-by: Samuel Pitoiset Reviewed-by: Bas Nieuwenhuizen --- src/amd/llvm/ac_nir_to_llvm.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/amd/llvm/ac_nir_to_llvm.c b/src/amd/llvm/ac_nir_to_llvm.c index 4c8216dbe73..d69b8c90238 100644 --- a/src/amd/llvm/ac_nir_to_llvm.c +++ b/src/amd/llvm/ac_nir_to_llvm.c @@ -3758,11 +3758,21 @@ static void visit_intrinsic(struct ac_nir_context *ctx, break; } case nir_intrinsic_load_constant: { + unsigned base = nir_intrinsic_base(instr); + unsigned range = nir_intrinsic_range(instr); + LLVMValueRef offset = get_src(ctx, instr->src[0]); - LLVMValueRef base = LLVMConstInt(ctx->ac.i32, - nir_intrinsic_base(instr), - false); - offset = LLVMBuildAdd(ctx->ac.builder, offset, base, ""); + offset = LLVMBuildAdd(ctx->ac.builder, offset, + LLVMConstInt(ctx->ac.i32, base, false), ""); + + /* Clamp the offset to avoid out-of-bound access because global + * instructions can't handle them. + */ + LLVMValueRef size = LLVMConstInt(ctx->ac.i32, base + range, false); + LLVMValueRef cond = LLVMBuildICmp(ctx->ac.builder, LLVMIntULT, + offset, size, ""); + offset = LLVMBuildSelect(ctx->ac.builder, cond, offset, size, ""); + LLVMValueRef ptr = ac_build_gep0(&ctx->ac, ctx->constant_data, offset); LLVMTypeRef comp_type = -- 2.30.2