mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Fix issue where array comparison would emit the wrong basic block reference to phi when underlying comparison would emit a block.
This commit is contained in:
@@ -131,8 +131,10 @@
|
||||
- Add checks to prevent incorrect alignment on malloc.
|
||||
- Updated clamp.
|
||||
- Added `Clock` and `DateTime`.
|
||||
- Added posix socket functions.
|
||||
|
||||
### Fixes
|
||||
- Fix to bug when comparing nested arrays.
|
||||
- Fix to bug when a macro is using rethrow.
|
||||
- Fixes bug initializing a const struct with a const struct value.
|
||||
- Fixes bug when `void` is passed to an "any"-vararg.
|
||||
|
||||
@@ -3509,13 +3509,25 @@ static void llvm_emit_subarray_comp(GenContext *c, BEValue *be_value, BEValue *l
|
||||
|
||||
}
|
||||
|
||||
INLINE bool should_inline_array_comp(ArraySize len, Type *base_type_lowered)
|
||||
{
|
||||
switch (base_type_lowered->type_kind)
|
||||
{
|
||||
case TYPE_ARRAY:
|
||||
return should_inline_array_comp(base_type_lowered->array.len * len, type_lowering(base_type_lowered->array.base));
|
||||
case TYPE_SUBARRAY:
|
||||
return len <= 4;
|
||||
default:
|
||||
return len <= 16;
|
||||
}
|
||||
}
|
||||
static void llvm_emit_array_comp(GenContext *c, BEValue *be_value, BEValue *lhs, BEValue *rhs, BinaryOp binary_op)
|
||||
{
|
||||
bool want_match = binary_op == BINARYOP_EQ;
|
||||
ArraySize len = lhs->type->array.len;
|
||||
Type *array_base_type = type_lowering(lhs->type->array.base);
|
||||
LLVMTypeRef array_type = llvm_get_type(c, lhs->type);
|
||||
if (len <= 16)
|
||||
if (should_inline_array_comp(len, array_base_type))
|
||||
{
|
||||
LLVMBasicBlockRef blocks[17];
|
||||
LLVMValueRef value_block[17];
|
||||
@@ -3525,7 +3537,7 @@ static void llvm_emit_array_comp(GenContext *c, BEValue *be_value, BEValue *lhs,
|
||||
llvm_value_addr(c, rhs);
|
||||
LLVMValueRef success = LLVMConstInt(c->bool_type, want_match ? 1 : 0, false);
|
||||
LLVMValueRef failure = LLVMConstInt(c->bool_type, want_match ? 0 : 1, false);
|
||||
blocks[0] = c->current_block;
|
||||
|
||||
for (unsigned i = 0; i < len; i++)
|
||||
{
|
||||
value_block[i] = failure;
|
||||
@@ -3539,11 +3551,9 @@ static void llvm_emit_array_comp(GenContext *c, BEValue *be_value, BEValue *lhs,
|
||||
llvm_value_set_address(&rhs_v, rhs_ptr, array_base_type, align_rhs);
|
||||
BEValue comp;
|
||||
llvm_emit_comp(c, &comp, &lhs_v, &rhs_v, BINARYOP_EQ);
|
||||
blocks[i] = c->current_block;
|
||||
LLVMBasicBlockRef block = ok_block;
|
||||
if (i < len - 1)
|
||||
{
|
||||
block = blocks[i + 1] = llvm_basic_block_new(c, "next_check");
|
||||
}
|
||||
block = i < len - 1 ? llvm_basic_block_new(c, "next_check") : block;
|
||||
llvm_emit_cond_br(c, &comp, block, exit_block);
|
||||
llvm_emit_block(c, block);
|
||||
}
|
||||
@@ -3560,7 +3570,8 @@ static void llvm_emit_array_comp(GenContext *c, BEValue *be_value, BEValue *lhs,
|
||||
LLVMBasicBlockRef exit = llvm_basic_block_new(c, "array_cmp_exit");
|
||||
LLVMBasicBlockRef loop_begin = llvm_basic_block_new(c, "array_loop_start");
|
||||
LLVMBasicBlockRef comparison = llvm_basic_block_new(c, "array_loop_comparison");
|
||||
|
||||
LLVMBasicBlockRef comparison_phi;
|
||||
LLVMBasicBlockRef loop_begin_phi;
|
||||
LLVMValueRef len_val = llvm_const_int(c, type_usz, len);
|
||||
LLVMValueRef one = llvm_const_int(c, type_usz, 1);
|
||||
BEValue index_var;
|
||||
@@ -3581,12 +3592,14 @@ static void llvm_emit_array_comp(GenContext *c, BEValue *be_value, BEValue *lhs,
|
||||
llvm_value_set_address(&rhs_v, rhs_ptr, array_base_type, align_rhs);
|
||||
BEValue comp;
|
||||
llvm_emit_comp(c, &comp, &lhs_v, &rhs_v, BINARYOP_EQ);
|
||||
loop_begin_phi = c->current_block;
|
||||
llvm_emit_cond_br(c, &comp, comparison, exit);
|
||||
llvm_emit_block(c, comparison);
|
||||
|
||||
LLVMValueRef new_index = LLVMBuildAdd(c->builder, index, one, "inc");
|
||||
llvm_store_raw(c, &index_var, new_index);
|
||||
llvm_emit_int_comp_raw(c, &comp, type_usz, type_usz, new_index, len_val, BINARYOP_LT);
|
||||
comparison_phi = c->current_block;
|
||||
llvm_emit_cond_br(c, &comp, loop_begin, exit);
|
||||
llvm_emit_block(c, exit);
|
||||
LLVMValueRef phi = LLVMBuildPhi(c->builder, c->bool_type, "array_cmp_phi");
|
||||
@@ -3594,7 +3607,7 @@ static void llvm_emit_array_comp(GenContext *c, BEValue *be_value, BEValue *lhs,
|
||||
LLVMValueRef success = LLVMConstInt(c->bool_type, want_match ? 1 : 0, false);
|
||||
LLVMValueRef failure = LLVMConstInt(c->bool_type, want_match ? 0 : 1, false);
|
||||
LLVMValueRef logic_values[3] = { success, failure };
|
||||
LLVMBasicBlockRef blocks[3] = { comparison, loop_begin };
|
||||
LLVMBasicBlockRef blocks[3] = { comparison_phi, loop_begin_phi };
|
||||
LLVMAddIncoming(phi, logic_values, blocks, 2);
|
||||
llvm_value_set(be_value, phi, type_bool);
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
#define COMPILER_VERSION "0.4.553"
|
||||
#define COMPILER_VERSION "0.4.554"
|
||||
156
test/test_suite/arrays/array_comparison_2.c3t
Normal file
156
test/test_suite/arrays/array_comparison_2.c3t
Normal file
@@ -0,0 +1,156 @@
|
||||
// #target: macos-x64
|
||||
module test;
|
||||
|
||||
fn void main()
|
||||
{
|
||||
int[2][2] x;
|
||||
int[2][2] y;
|
||||
bool match = x == y;
|
||||
int[2][2][8] z;
|
||||
int[2][2][8] w;
|
||||
match = z == w;
|
||||
}
|
||||
|
||||
/* #expect: test.ll
|
||||
|
||||
define void @test.main() #0 {
|
||||
entry:
|
||||
%x = alloca [2 x [2 x i32]], align 16
|
||||
%y = alloca [2 x [2 x i32]], align 16
|
||||
%match = alloca i8, align 1
|
||||
%z = alloca [8 x [2 x [2 x i32]]], align 16
|
||||
%w = alloca [8 x [2 x [2 x i32]]], align 16
|
||||
%cmp.idx = alloca i64, align 8
|
||||
%0 = getelementptr inbounds [2 x [2 x i32]], ptr %x, i64 0, i64 0
|
||||
%1 = getelementptr inbounds [2 x i32], ptr %0, i64 0, i64 0
|
||||
store i32 0, ptr %1, align 4
|
||||
%2 = getelementptr inbounds [2 x i32], ptr %0, i64 0, i64 1
|
||||
store i32 0, ptr %2, align 4
|
||||
%3 = getelementptr inbounds [2 x [2 x i32]], ptr %x, i64 0, i64 1
|
||||
%4 = getelementptr inbounds [2 x i32], ptr %3, i64 0, i64 0
|
||||
store i32 0, ptr %4, align 4
|
||||
%5 = getelementptr inbounds [2 x i32], ptr %3, i64 0, i64 1
|
||||
store i32 0, ptr %5, align 4
|
||||
%6 = getelementptr inbounds [2 x [2 x i32]], ptr %y, i64 0, i64 0
|
||||
%7 = getelementptr inbounds [2 x i32], ptr %6, i64 0, i64 0
|
||||
store i32 0, ptr %7, align 4
|
||||
%8 = getelementptr inbounds [2 x i32], ptr %6, i64 0, i64 1
|
||||
store i32 0, ptr %8, align 4
|
||||
%9 = getelementptr inbounds [2 x [2 x i32]], ptr %y, i64 0, i64 1
|
||||
%10 = getelementptr inbounds [2 x i32], ptr %9, i64 0, i64 0
|
||||
store i32 0, ptr %10, align 4
|
||||
%11 = getelementptr inbounds [2 x i32], ptr %9, i64 0, i64 1
|
||||
store i32 0, ptr %11, align 4
|
||||
%12 = getelementptr inbounds [2 x [2 x i32]], ptr %x, i64 0, i64 0
|
||||
%13 = getelementptr inbounds [2 x [2 x i32]], ptr %y, i64 0, i64 0
|
||||
%14 = getelementptr inbounds [2 x i32], ptr %12, i64 0, i64 0
|
||||
%15 = getelementptr inbounds [2 x i32], ptr %13, i64 0, i64 0
|
||||
%16 = load i32, ptr %14, align 4
|
||||
%17 = load i32, ptr %15, align 4
|
||||
%eq = icmp eq i32 %16, %17
|
||||
br i1 %eq, label %next_check, label %exit
|
||||
next_check: ; preds = %entry
|
||||
%18 = getelementptr inbounds [2 x i32], ptr %12, i64 0, i64 1
|
||||
%19 = getelementptr inbounds [2 x i32], ptr %13, i64 0, i64 1
|
||||
%20 = load i32, ptr %18, align 4
|
||||
%21 = load i32, ptr %19, align 4
|
||||
%eq1 = icmp eq i32 %20, %21
|
||||
br i1 %eq1, label %match2, label %exit
|
||||
match2: ; preds = %next_check
|
||||
br label %exit
|
||||
exit: ; preds = %match2, %next_check, %entry
|
||||
%array_cmp_phi = phi i1 [ false, %entry ], [ false, %next_check ], [ true, %match2 ]
|
||||
br i1 %array_cmp_phi, label %next_check3, label %exit11
|
||||
next_check3: ; preds = %exit
|
||||
%22 = getelementptr inbounds [2 x [2 x i32]], ptr %x, i64 0, i64 1
|
||||
%23 = getelementptr inbounds [2 x [2 x i32]], ptr %y, i64 0, i64 1
|
||||
%24 = getelementptr inbounds [2 x i32], ptr %22, i64 0, i64 0
|
||||
%25 = getelementptr inbounds [2 x i32], ptr %23, i64 0, i64 0
|
||||
%26 = load i32, ptr %24, align 4
|
||||
%27 = load i32, ptr %25, align 4
|
||||
%eq4 = icmp eq i32 %26, %27
|
||||
br i1 %eq4, label %next_check5, label %exit8
|
||||
next_check5: ; preds = %next_check3
|
||||
%28 = getelementptr inbounds [2 x i32], ptr %22, i64 0, i64 1
|
||||
%29 = getelementptr inbounds [2 x i32], ptr %23, i64 0, i64 1
|
||||
%30 = load i32, ptr %28, align 4
|
||||
%31 = load i32, ptr %29, align 4
|
||||
%eq6 = icmp eq i32 %30, %31
|
||||
br i1 %eq6, label %match7, label %exit8
|
||||
match7: ; preds = %next_check5
|
||||
br label %exit8
|
||||
exit8: ; preds = %match7, %next_check5, %next_check3
|
||||
%array_cmp_phi9 = phi i1 [ false, %next_check3 ], [ false, %next_check5 ], [ true, %match7 ]
|
||||
br i1 %array_cmp_phi9, label %match10, label %exit11
|
||||
match10: ; preds = %exit8
|
||||
br label %exit11
|
||||
exit11: ; preds = %match10, %exit8, %exit
|
||||
%array_cmp_phi12 = phi i1 [ false, %exit ], [ false, %exit8 ], [ true, %match10 ]
|
||||
%32 = zext i1 %array_cmp_phi12 to i8
|
||||
store i8 %32, ptr %match, align 1
|
||||
call void @llvm.memset.p0.i64(ptr align 16 %z, i8 0, i64 128, i1 false)
|
||||
call void @llvm.memset.p0.i64(ptr align 16 %w, i8 0, i64 128, i1 false)
|
||||
store i64 0, ptr %cmp.idx, align 8
|
||||
br label %array_loop_start
|
||||
array_loop_start: ; preds = %array_loop_comparison, %exit11
|
||||
%33 = load i64, ptr %cmp.idx, align 8
|
||||
%34 = getelementptr inbounds [8 x [2 x [2 x i32]]], ptr %z, i64 0, i64 %33
|
||||
%35 = getelementptr inbounds [8 x [2 x [2 x i32]]], ptr %w, i64 0, i64 %33
|
||||
%36 = getelementptr inbounds [2 x [2 x i32]], ptr %34, i64 0, i64 0
|
||||
%37 = getelementptr inbounds [2 x [2 x i32]], ptr %35, i64 0, i64 0
|
||||
%38 = getelementptr inbounds [2 x i32], ptr %36, i64 0, i64 0
|
||||
%39 = getelementptr inbounds [2 x i32], ptr %37, i64 0, i64 0
|
||||
%40 = load i32, ptr %38, align 4
|
||||
%41 = load i32, ptr %39, align 4
|
||||
%eq13 = icmp eq i32 %40, %41
|
||||
br i1 %eq13, label %next_check14, label %exit17
|
||||
next_check14: ; preds = %array_loop_start
|
||||
%42 = getelementptr inbounds [2 x i32], ptr %36, i64 0, i64 1
|
||||
%43 = getelementptr inbounds [2 x i32], ptr %37, i64 0, i64 1
|
||||
%44 = load i32, ptr %42, align 4
|
||||
%45 = load i32, ptr %43, align 4
|
||||
%eq15 = icmp eq i32 %44, %45
|
||||
br i1 %eq15, label %match16, label %exit17
|
||||
match16: ; preds = %next_check14
|
||||
br label %exit17
|
||||
exit17: ; preds = %match16, %next_check14, %array_loop_start
|
||||
%array_cmp_phi18 = phi i1 [ false, %array_loop_start ], [ false, %next_check14 ], [ true, %match16 ]
|
||||
br i1 %array_cmp_phi18, label %next_check19, label %exit27
|
||||
next_check19: ; preds = %exit17
|
||||
%46 = getelementptr inbounds [2 x [2 x i32]], ptr %34, i64 0, i64 1
|
||||
%47 = getelementptr inbounds [2 x [2 x i32]], ptr %35, i64 0, i64 1
|
||||
%48 = getelementptr inbounds [2 x i32], ptr %46, i64 0, i64 0
|
||||
%49 = getelementptr inbounds [2 x i32], ptr %47, i64 0, i64 0
|
||||
%50 = load i32, ptr %48, align 4
|
||||
%51 = load i32, ptr %49, align 4
|
||||
%eq20 = icmp eq i32 %50, %51
|
||||
br i1 %eq20, label %next_check21, label %exit24
|
||||
next_check21: ; preds = %next_check19
|
||||
%52 = getelementptr inbounds [2 x i32], ptr %46, i64 0, i64 1
|
||||
%53 = getelementptr inbounds [2 x i32], ptr %47, i64 0, i64 1
|
||||
%54 = load i32, ptr %52, align 4
|
||||
%55 = load i32, ptr %53, align 4
|
||||
%eq22 = icmp eq i32 %54, %55
|
||||
br i1 %eq22, label %match23, label %exit24
|
||||
match23: ; preds = %next_check21
|
||||
br label %exit24
|
||||
exit24: ; preds = %match23, %next_check21, %next_check19
|
||||
%array_cmp_phi25 = phi i1 [ false, %next_check19 ], [ false, %next_check21 ], [ true, %match23 ]
|
||||
br i1 %array_cmp_phi25, label %match26, label %exit27
|
||||
match26: ; preds = %exit24
|
||||
br label %exit27
|
||||
exit27: ; preds = %match26, %exit24, %exit17
|
||||
%array_cmp_phi28 = phi i1 [ false, %exit17 ], [ false, %exit24 ], [ true, %match26 ]
|
||||
br i1 %array_cmp_phi28, label %array_loop_comparison, label %array_cmp_exit
|
||||
array_loop_comparison: ; preds = %exit27
|
||||
%inc = add i64 %33, 1
|
||||
store i64 %inc, ptr %cmp.idx, align 8
|
||||
%lt = icmp ult i64 %inc, 8
|
||||
br i1 %lt, label %array_loop_start, label %array_cmp_exit
|
||||
array_cmp_exit: ; preds = %array_loop_comparison, %exit27
|
||||
%array_cmp_phi29 = phi i1 [ true, %array_loop_comparison ], [ false, %exit27 ]
|
||||
%56 = zext i1 %array_cmp_phi29 to i8
|
||||
store i8 %56, ptr %match, align 1
|
||||
ret void
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user