ac: allow control flow statements in NIR callbacks
authorMarek Olšák <marek.olsak@amd.com>
Wed, 24 Jul 2019 21:19:38 +0000 (17:19 -0400)
committerMarek Olšák <marek.olsak@amd.com>
Wed, 31 Jul 2019 02:06:23 +0000 (22:06 -0400)
This fixes a crash when compiling geometry shaders on radeonsi.

src/amd/common/ac_llvm_build.c
src/amd/common/ac_llvm_build.h

index 278f889343211750009fb278ab95b06dbdea4951..d916fea6771bfbf285fdb7626b7a19b0fe3e5559 100644 (file)
@@ -127,14 +127,15 @@ ac_llvm_context_init(struct ac_llvm_context *ctx,
                                                        "amdgpu.uniform", 14);
 
        ctx->empty_md = LLVMMDNodeInContext(ctx->context, NULL, 0);
+       ctx->flow = calloc(1, sizeof(*ctx->flow));
 }
 
 void
 ac_llvm_context_dispose(struct ac_llvm_context *ctx)
 {
+       free(ctx->flow->stack);
        free(ctx->flow);
        ctx->flow = NULL;
-       ctx->flow_depth_max = 0;
 }
 
 int
@@ -3495,17 +3496,17 @@ LLVMTypeRef ac_array_in_const32_addr_space(LLVMTypeRef elem_type)
 static struct ac_llvm_flow *
 get_current_flow(struct ac_llvm_context *ctx)
 {
-       if (ctx->flow_depth > 0)
-               return &ctx->flow[ctx->flow_depth - 1];
+       if (ctx->flow->depth > 0)
+               return &ctx->flow->stack[ctx->flow->depth - 1];
        return NULL;
 }
 
 static struct ac_llvm_flow *
 get_innermost_loop(struct ac_llvm_context *ctx)
 {
-       for (unsigned i = ctx->flow_depth; i > 0; --i) {
-               if (ctx->flow[i - 1].loop_entry_block)
-                       return &ctx->flow[i - 1];
+       for (unsigned i = ctx->flow->depth; i > 0; --i) {
+               if (ctx->flow->stack[i - 1].loop_entry_block)
+                       return &ctx->flow->stack[i - 1];
        }
        return NULL;
 }
@@ -3515,16 +3516,16 @@ push_flow(struct ac_llvm_context *ctx)
 {
        struct ac_llvm_flow *flow;
 
-       if (ctx->flow_depth >= ctx->flow_depth_max) {
-               unsigned new_max = MAX2(ctx->flow_depth << 1,
+       if (ctx->flow->depth >= ctx->flow->depth_max) {
+               unsigned new_max = MAX2(ctx->flow->depth << 1,
                                        AC_LLVM_INITIAL_CF_DEPTH);
 
-               ctx->flow = realloc(ctx->flow, new_max * sizeof(*ctx->flow));
-               ctx->flow_depth_max = new_max;
+               ctx->flow->stack = realloc(ctx->flow->stack, new_max * sizeof(*ctx->flow->stack));
+               ctx->flow->depth_max = new_max;
        }
 
-       flow = &ctx->flow[ctx->flow_depth];
-       ctx->flow_depth++;
+       flow = &ctx->flow->stack[ctx->flow->depth];
+       ctx->flow->depth++;
 
        flow->next_block = NULL;
        flow->loop_entry_block = NULL;
@@ -3544,10 +3545,10 @@ static void set_basicblock_name(LLVMBasicBlockRef bb, const char *base,
 static LLVMBasicBlockRef append_basic_block(struct ac_llvm_context *ctx,
                                            const char *name)
 {
-       assert(ctx->flow_depth >= 1);
+       assert(ctx->flow->depth >= 1);
 
-       if (ctx->flow_depth >= 2) {
-               struct ac_llvm_flow *flow = &ctx->flow[ctx->flow_depth - 2];
+       if (ctx->flow->depth >= 2) {
+               struct ac_llvm_flow *flow = &ctx->flow->stack[ctx->flow->depth - 2];
 
                return LLVMInsertBasicBlockInContext(ctx->context,
                                                     flow->next_block, name);
@@ -3617,7 +3618,7 @@ void ac_build_endif(struct ac_llvm_context *ctx, int label_id)
        LLVMPositionBuilderAtEnd(ctx->builder, current_branch->next_block);
        set_basicblock_name(current_branch->next_block, "endif", label_id);
 
-       ctx->flow_depth--;
+       ctx->flow->depth--;
 }
 
 void ac_build_endloop(struct ac_llvm_context *ctx, int label_id)
@@ -3630,7 +3631,7 @@ void ac_build_endloop(struct ac_llvm_context *ctx, int label_id)
 
        LLVMPositionBuilderAtEnd(ctx->builder, current_loop->next_block);
        set_basicblock_name(current_loop->next_block, "endloop", label_id);
-       ctx->flow_depth--;
+       ctx->flow->depth--;
 }
 
 void ac_build_ifcc(struct ac_llvm_context *ctx, LLVMValueRef cond, int label_id)
index 8fcede66fb2b4997179d25515ff6fe94ce000969..e460d14e177684b1eceaf64e16943cfb795dd082 100644 (file)
@@ -51,6 +51,12 @@ struct ac_llvm_flow;
 struct ac_llvm_compiler;
 enum ac_float_mode;
 
+struct ac_llvm_flow_state {
+       struct ac_llvm_flow *stack;
+       unsigned depth_max;
+       unsigned depth;
+};
+
 struct ac_llvm_context {
        LLVMContextRef context;
        LLVMModuleRef module;
@@ -93,9 +99,11 @@ struct ac_llvm_context {
        LLVMValueRef i1true;
        LLVMValueRef i1false;
 
-       struct ac_llvm_flow *flow;
-       unsigned flow_depth;
-       unsigned flow_depth_max;
+       /* Since ac_nir_translate makes a local copy of ac_llvm_context, there
+        * are two ac_llvm_contexts. Declare a pointer here, so that the control
+        * flow stack is shared by both ac_llvm_contexts.
+        */
+       struct ac_llvm_flow_state *flow;
 
        unsigned range_md_kind;
        unsigned invariant_load_md_kind;