radeon/llvm: Dynamically allocate branch/loop stack arrays
authorMichel Dänzer <michel.daenzer@amd.com>
Tue, 28 Oct 2014 02:28:29 +0000 (11:28 +0900)
committerMichel Dänzer <michel@daenzer.net>
Wed, 29 Oct 2014 10:01:25 +0000 (19:01 +0900)
This prevents us from silently overflowing the stack arrays, and allows
arbitrary stack depths.

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=85454

Cc: mesa-stable@lists.freedesktop.org
Reported-and-Tested-by: Nick Sarnie <commendsarnex@gmail.com>
Reviewed-by: Marek Olšák <marek.olsak@amd.com>
src/gallium/drivers/radeon/radeon_llvm.h
src/gallium/drivers/radeon/radeon_setup_tgsi_llvm.c

index 00714fb6bca30d7863a72faad9852969b4f536f6..8612ef8daf75bc92e8ac5e483e6d2f34ae68c71e 100644 (file)
 
 #define RADEON_LLVM_MAX_INPUTS 32 * 4
 #define RADEON_LLVM_MAX_OUTPUTS 32 * 4
-#define RADEON_LLVM_MAX_BRANCH_DEPTH 16
-#define RADEON_LLVM_MAX_LOOP_DEPTH 16
 #define RADEON_LLVM_MAX_ARRAYS 16
 
+#define RADEON_LLVM_INITIAL_CF_DEPTH 4
+
 #define RADEON_LLVM_MAX_SYSTEM_VALUES 4
 
 struct radeon_llvm_branch {
@@ -122,11 +122,13 @@ struct radeon_llvm_context {
 
        /*=== Private Members ===*/
 
-       struct radeon_llvm_branch branch[RADEON_LLVM_MAX_BRANCH_DEPTH];
-       struct radeon_llvm_loop loop[RADEON_LLVM_MAX_LOOP_DEPTH];
+       struct radeon_llvm_branch *branch;
+       struct radeon_llvm_loop *loop;
 
        unsigned branch_depth;
+       unsigned branch_depth_max;
        unsigned loop_depth;
+       unsigned loop_depth_max;
 
        struct tgsi_declaration_range arrays[RADEON_LLVM_MAX_ARRAYS];
        unsigned num_arrays;
index 2fa23ed087c5d7996da3d28ffe4fa2c3f7824174..c30a9d05e3a89ee21cf89d27287a5822369c4107 100644 (file)
@@ -446,7 +446,19 @@ static void bgnloop_emit(
                                                endloop_block, "LOOP");
        LLVMBuildBr(gallivm->builder, loop_block);
        LLVMPositionBuilderAtEnd(gallivm->builder, loop_block);
-       ctx->loop_depth++;
+
+       if (++ctx->loop_depth > ctx->loop_depth_max) {
+               unsigned new_max = ctx->loop_depth_max << 1;
+
+               if (!new_max)
+                       new_max = RADEON_LLVM_INITIAL_CF_DEPTH;
+
+               ctx->loop = REALLOC(ctx->loop, ctx->loop_depth_max *
+                                   sizeof(ctx->loop[0]),
+                                   new_max * sizeof(ctx->loop[0]));
+               ctx->loop_depth_max = new_max;
+       }
+
        ctx->loop[ctx->loop_depth - 1].loop_block = loop_block;
        ctx->loop[ctx->loop_depth - 1].endloop_block = endloop_block;
 }
@@ -577,7 +589,18 @@ static void if_cond_emit(
        LLVMBuildCondBr(gallivm->builder, cond, if_block, else_block);
        LLVMPositionBuilderAtEnd(gallivm->builder, if_block);
 
-       ctx->branch_depth++;
+       if (++ctx->branch_depth > ctx->branch_depth_max) {
+               unsigned new_max = ctx->branch_depth_max << 1;
+
+               if (!new_max)
+                       new_max = RADEON_LLVM_INITIAL_CF_DEPTH;
+
+               ctx->branch = REALLOC(ctx->branch, ctx->branch_depth_max *
+                                     sizeof(ctx->branch[0]),
+                                     new_max * sizeof(ctx->branch[0]));
+               ctx->branch_depth_max = new_max;
+       }
+
        ctx->branch[ctx->branch_depth - 1].endif_block = endif_block;
        ctx->branch[ctx->branch_depth - 1].if_block = if_block;
        ctx->branch[ctx->branch_depth - 1].else_block = else_block;
@@ -1440,4 +1463,10 @@ void radeon_llvm_dispose(struct radeon_llvm_context * ctx)
        LLVMContextDispose(ctx->soa.bld_base.base.gallivm->context);
        FREE(ctx->temps);
        ctx->temps = NULL;
+       FREE(ctx->loop);
+       ctx->loop = NULL;
+       ctx->loop_depth_max = 0;
+       FREE(ctx->branch);
+       ctx->branch = NULL;
+       ctx->branch_depth_max = 0;
 }