From e83195b56b45816ccf3cbd1e635564c6a1671f59 Mon Sep 17 00:00:00 2001 From: Luc Van Oostenryck Date: Fri, 23 Oct 2020 00:29:12 +0200 Subject: llvm: fix crash with llvm-11 / use real phi-nodes sparse-llvm crashes with LLVM-11. From what I can see, it's because LLVM-11 doesn't like anymore that an instruction is first created unattached to a basic block (LLVMClearInsertionPosition()) and inserted at some later step (LLVMInsertIntoBuilder()). Since the corresponding function still exist I suppose they're working correctly and sparse-llvm somehow misuse them. I don't know. However, this functionality is only used to create the alloca instructions used to simulate the phi-nodes. So, fix this crash by using real phi instructions for the phi-nodes. Signed-off-by: Luc Van Oostenryck --- sparse-llvm.c | 75 +++++++++++++++++++++++------------------------------------ 1 file changed, 29 insertions(+), 46 deletions(-) diff --git a/sparse-llvm.c b/sparse-llvm.c index c7a9fbb7..c984dc87 100644 --- a/sparse-llvm.c +++ b/sparse-llvm.c @@ -826,37 +826,14 @@ static void output_op_call(struct function *fn, struct instruction *insn) static void output_op_phisrc(struct function *fn, struct instruction *insn) { - LLVMValueRef v; - struct instruction *phi; - - assert(insn->target->priv == NULL); - - /* target = src */ - v = get_operand(fn, insn->type, insn->phi_src); - - FOR_EACH_PTR(insn->phi_users, phi) { - LLVMValueRef load, ptr; - - assert(phi->opcode == OP_PHI); - /* phi must be load from alloca */ - load = phi->target->priv; - assert(LLVMGetInstructionOpcode(load) == LLVMLoad); - ptr = LLVMGetOperand(load, 0); - /* store v to alloca */ - LLVMBuildStore(fn->builder, v, ptr); - } END_FOR_EACH_PTR(phi); + insn->src->priv = get_operand(fn, insn->type, insn->src); } static void output_op_phi(struct function *fn, struct instruction *insn) { - LLVMValueRef load = insn->target->priv; - - /* forward load */ - assert(LLVMGetInstructionOpcode(load) == LLVMLoad); - /* forward load has no parent block */ - assert(!LLVMGetInstructionParent(load)); - /* finalize load in current block */ - LLVMInsertIntoBuilder(fn->builder, load); + LLVMTypeRef dst_type = insn_symbol_type(insn); + + insn->target->priv = LLVMBuildPhi(fn->builder, dst_type, ""); } static void output_op_ptrcast(struct function *fn, struct instruction *insn) @@ -1161,30 +1138,11 @@ static void output_fn(LLVMModuleRef module, struct entrypoint *ep) static int nr_bb; LLVMBasicBlockRef bbr; char bbname[32]; - struct instruction *insn; sprintf(bbname, "L%d", nr_bb++); bbr = LLVMAppendBasicBlock(function.fn, bbname); bb->priv = bbr; - - /* allocate alloca for each phi */ - FOR_EACH_PTR(bb->insns, insn) { - LLVMBasicBlockRef entrybbr; - LLVMTypeRef phi_type; - LLVMValueRef ptr; - - if (!insn->bb || insn->opcode != OP_PHI) - continue; - /* insert alloca into entry block */ - entrybbr = LLVMGetEntryBasicBlock(function.fn); - LLVMPositionBuilderAtEnd(function.builder, entrybbr); - phi_type = insn_symbol_type(insn); - ptr = LLVMBuildAlloca(function.builder, phi_type, ""); - /* emit forward load for phi */ - LLVMClearInsertionPosition(function.builder); - insn->target->priv = LLVMBuildLoad(function.builder, ptr, "phi"); - } END_FOR_EACH_PTR(insn); } END_FOR_EACH_PTR(bb); @@ -1194,6 +1152,31 @@ static void output_fn(LLVMModuleRef module, struct entrypoint *ep) output_bb(&function, bb); } END_FOR_EACH_PTR(bb); + + FOR_EACH_PTR(ep->bbs, bb) { // complete the OP_PHIs + struct instruction *insn; + + FOR_EACH_PTR(bb->insns, insn) { + pseudo_t phi; + + if (!insn->bb || insn->opcode != OP_PHI) + continue; + + FOR_EACH_PTR(insn->phi_list, phi) { + struct instruction *phisrc; + LLVMBasicBlockRef bref; + LLVMValueRef vref; + + if (phi == VOID) + continue; + + phisrc = phi->def; + bref = phisrc->bb->priv; + vref = phisrc->src->priv; + LLVMAddIncoming(insn->target->priv, &vref, &bref, 1); + } END_FOR_EACH_PTR(phi); + } END_FOR_EACH_PTR(insn); + } END_FOR_EACH_PTR(bb); } static LLVMValueRef output_data(LLVMModuleRef module, struct symbol *sym) -- cgit 1.2.3-korg