summaryrefslogtreecommitdiffstats
path: root/src/amd
diff options
context:
space:
mode:
authorMarek Olšák <[email protected]>2019-07-24 17:19:38 -0400
committerMarek Olšák <[email protected]>2019-07-30 22:06:23 -0400
commitf6eca14f1b0b6e964821e59fd10f4dc00596a18c (patch)
treebd6f1f895bdb8a11cc76487990c99f6e9f9aff8d /src/amd
parentbfea7e4d2965269bff8f1f6449cb99c312fd7384 (diff)
ac: allow control flow statements in NIR callbacks
This fixes a crash when compiling geometry shaders on radeonsi.
Diffstat (limited to 'src/amd')
-rw-r--r--src/amd/common/ac_llvm_build.c35
-rw-r--r--src/amd/common/ac_llvm_build.h14
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;