From f6eca14f1b0b6e964821e59fd10f4dc00596a18c Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Wed, 24 Jul 2019 17:19:38 -0400 Subject: [PATCH] ac: allow control flow statements in NIR callbacks This fixes a crash when compiling geometry shaders on radeonsi. --- src/amd/common/ac_llvm_build.c | 35 +++++++++++++++++----------------- src/amd/common/ac_llvm_build.h | 14 +++++++++++--- 2 files changed, 29 insertions(+), 20 deletions(-) diff --git a/src/amd/common/ac_llvm_build.c b/src/amd/common/ac_llvm_build.c index 278f8893432..d916fea6771 100644 --- a/src/amd/common/ac_llvm_build.c +++ b/src/amd/common/ac_llvm_build.c @@ -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) diff --git a/src/amd/common/ac_llvm_build.h b/src/amd/common/ac_llvm_build.h index 8fcede66fb2..e460d14e177 100644 --- a/src/amd/common/ac_llvm_build.h +++ b/src/amd/common/ac_llvm_build.h @@ -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; -- 2.30.2