aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2020-10-23 00:29:12 +0200
committerLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2020-10-23 00:51:18 +0200
commite83195b56b45816ccf3cbd1e635564c6a1671f59 (patch)
tree60443d25f109ff497ee0d866ce587f018d47b3eb
parent6746138ae86af0e850fd155b43a8a0b9c398d907 (diff)
downloadsparse-maint-v0.6.3.tar.gz
llvm: fix crash with llvm-11 / use real phi-nodesmaint-v0.6.3
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 <luc.vanoostenryck@gmail.com>
-rw-r--r--sparse-llvm.c75
1 files 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)