Skip to content

Commit

Permalink
Dynamic protocols. Correctly widen unsigned array indices (see #1029)
Browse files Browse the repository at this point in the history
  • Loading branch information
lerno committed Oct 5, 2023
1 parent 49c4595 commit 70f906c
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 15 deletions.
1 change: 1 addition & 0 deletions releasenotes.md
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@
- Added posix socket functions.
### Fixes
- Indexing into arrays would not always widen the index safely.
- Macros with implicit return didn't correctly deduct the return type.
- Reevaluating a bitstruct (due to checked) would break.
- Fix missing comparison between `any`.
Expand Down
31 changes: 21 additions & 10 deletions src/compiler/llvm_codegen_expr.c
Original file line number Diff line number Diff line change
Expand Up @@ -606,7 +606,7 @@ static inline void llvm_emit_subscript_addr_with_base(GenContext *c, BEValue *re
case TYPE_VECTOR:
{
AlignSize alignment;
LLVMValueRef ptr = llvm_emit_array_gep_raw_index(c, parent->value, llvm_get_type(c, type), index->value, parent->alignment, &alignment);
LLVMValueRef ptr = llvm_emit_array_gep_raw_index(c, parent->value, llvm_get_type(c, type), index, parent->alignment, &alignment);
llvm_value_set_address(result, ptr, type->array.base, alignment);
return;
}
Expand Down Expand Up @@ -1167,7 +1167,7 @@ static inline void llvm_emit_access_addr(GenContext *c, BEValue *be_value, Expr
LLVMTypeRef value_type = llvm_get_type(c, type_get_array(member->type, vec_size(flat_type->decl->enums.values)));
AlignSize align = LLVMGetAlignment(member->backend_ref);
AlignSize alignment;
LLVMValueRef ptr = llvm_emit_array_gep_raw_index(c, member->backend_ref, value_type, be_value->value, align, &alignment);
LLVMValueRef ptr = llvm_emit_array_gep_raw_index(c, member->backend_ref, value_type, be_value, align, &alignment);
llvm_value_set_address(be_value, ptr, member->type, alignment);
return;
}
Expand Down Expand Up @@ -2966,7 +2966,7 @@ static void gencontext_emit_slice(GenContext *c, BEValue *be_value, Expr *expr)
{
// Move pointer
AlignSize alignment;
start_pointer = llvm_emit_array_gep_raw_index(c, parent.value, llvm_get_type(c, parent.type), start.value, type_abi_alignment(parent.type), &alignment);
start_pointer = llvm_emit_array_gep_raw_index(c, parent.value, llvm_get_type(c, parent.type), &start, type_abi_alignment(parent.type), &alignment);
break;
}
case TYPE_SUBARRAY:
Expand Down Expand Up @@ -3656,20 +3656,21 @@ static void llvm_emit_array_comp(GenContext *c, BEValue *be_value, BEValue *lhs,

AlignSize align_lhs;
BEValue lhs_v;
LLVMValueRef index = llvm_load_value(c, &index_var);
LLVMValueRef lhs_ptr = llvm_emit_array_gep_raw_index(c, lhs->value, array_type, index, lhs->alignment, &align_lhs);
BEValue index_copy = index_var;
llvm_value_rvalue(c, &index_copy);
LLVMValueRef lhs_ptr = llvm_emit_array_gep_raw_index(c, lhs->value, array_type, &index_copy, lhs->alignment, &align_lhs);
llvm_value_set_address(&lhs_v, lhs_ptr, array_base_type, align_lhs);
AlignSize align_rhs;
BEValue rhs_v;
LLVMValueRef rhs_ptr = llvm_emit_array_gep_raw_index(c, rhs->value, array_type, index, rhs->alignment, &align_rhs);
LLVMValueRef rhs_ptr = llvm_emit_array_gep_raw_index(c, rhs->value, array_type, &index_copy, rhs->alignment, &align_rhs);
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");
LLVMValueRef new_index = LLVMBuildAdd(c->builder, index_copy.value, 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;
Expand Down Expand Up @@ -4948,16 +4949,26 @@ LLVMValueRef llvm_emit_struct_gep_raw(GenContext *context, LLVMValueRef ptr, LLV
}


LLVMValueRef llvm_emit_array_gep_raw_index(GenContext *c, LLVMValueRef ptr, LLVMTypeRef array_type, LLVMValueRef index, AlignSize array_alignment, AlignSize *alignment)
LLVMValueRef llvm_emit_array_gep_raw_index(GenContext *c, LLVMValueRef ptr, LLVMTypeRef array_type, BEValue *index, AlignSize array_alignment, AlignSize *alignment)
{
LLVMValueRef index_val = llvm_load_value(c, index);
Type *index_type = index->type;
assert(type_is_integer(index_type));
if (type_is_unsigned(index_type) && type_size(index_type) < type_size(type_usz))
{
index_type = type_usz->canonical;
index_val = llvm_zext_trunc(c, index_val, llvm_get_type(c, index_type));
}
*alignment = type_min_alignment(llvm_store_size(c, LLVMGetElementType(array_type)), array_alignment);
LLVMValueRef idx[2] = { llvm_get_zero_raw(LLVMTypeOf(index)), index };
LLVMValueRef idx[2] = { llvm_get_zero(c, index_type), index_val };
return LLVMBuildInBoundsGEP2(c->builder, array_type, ptr, idx, 2, "");
}

LLVMValueRef llvm_emit_array_gep_raw(GenContext *c, LLVMValueRef ptr, LLVMTypeRef array_type, unsigned index, AlignSize array_alignment, AlignSize *alignment)
{
return llvm_emit_array_gep_raw_index(c, ptr, array_type, llvm_const_int(c, type_usz, index), array_alignment, alignment);
BEValue index_value;
llvm_value_set(&index_value, llvm_const_int(c, type_usz, index), type_usz);
return llvm_emit_array_gep_raw_index(c, ptr, array_type, &index_value, array_alignment, alignment);
}

LLVMValueRef llvm_emit_pointer_gep_raw(GenContext *c, LLVMTypeRef pointee_type, LLVMValueRef ptr, LLVMValueRef offset)
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/llvm_codegen_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -452,7 +452,7 @@ LLVMValueRef llvm_emit_aggregate_two(GenContext *c, Type *type, LLVMValueRef val
LLVMValueRef llvm_emit_struct_gep_raw(GenContext *context, LLVMValueRef ptr, LLVMTypeRef struct_type, unsigned index,
unsigned struct_alignment, AlignSize *alignment);
LLVMValueRef llvm_emit_array_gep_raw(GenContext *c, LLVMValueRef ptr, LLVMTypeRef array_type, unsigned index, AlignSize array_alignment, AlignSize *alignment);
LLVMValueRef llvm_emit_array_gep_raw_index(GenContext *c, LLVMValueRef ptr, LLVMTypeRef array_type, LLVMValueRef index, AlignSize array_alignment, AlignSize *alignment);
LLVMValueRef llvm_emit_array_gep_raw_index(GenContext *c, LLVMValueRef ptr, LLVMTypeRef array_type, BEValue *index, AlignSize array_alignment, AlignSize *alignment);
LLVMValueRef llvm_emit_pointer_gep_raw(GenContext *c, LLVMTypeRef pointee_type, LLVMValueRef ptr, LLVMValueRef offset);
LLVMValueRef llvm_emit_pointer_inbounds_gep_raw(GenContext *c, LLVMTypeRef pointee_type, LLVMValueRef ptr, LLVMValueRef offset);
LLVMValueRef llvm_emit_pointer_inbounds_gep_raw_index(GenContext *c, LLVMTypeRef pointee_type, LLVMValueRef ptr, ByteSize offset);
Expand Down
12 changes: 8 additions & 4 deletions test/test_suite/enumerations/enum_associated_value.c3t
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,20 @@ entry:
store i32 1, ptr %f, align 4
store i32 0, ptr %g, align 4
%0 = load i32, ptr %f, align 4
%1 = getelementptr inbounds [2 x i32], ptr @"test.Foo$val", i32 0, i32 %0
%zext = zext i32 %0 to i64
%1 = getelementptr inbounds [2 x i32], ptr @"test.Foo$val", i64 0, i64 %zext
%2 = load i32, ptr %1, align 4
%3 = load i32, ptr %f, align 4
%4 = getelementptr inbounds [2 x ptr], ptr @"test.Foo$testme", i32 0, i32 %3
%zext1 = zext i32 %3 to i64
%4 = getelementptr inbounds [2 x ptr], ptr @"test.Foo$testme", i64 0, i64 %zext1
%5 = load ptr, ptr %4, align 8
%6 = load i32, ptr %g, align 4
%7 = getelementptr inbounds [2 x i32], ptr @"test.Foo$val", i32 0, i32 %6
%zext2 = zext i32 %6 to i64
%7 = getelementptr inbounds [2 x i32], ptr @"test.Foo$val", i64 0, i64 %zext2
%8 = load i32, ptr %7, align 4
%9 = load i32, ptr %g, align 4
%10 = getelementptr inbounds [2 x ptr], ptr @"test.Foo$testme", i32 0, i32 %9
%zext3 = zext i32 %9 to i64
%10 = getelementptr inbounds [2 x ptr], ptr @"test.Foo$testme", i64 0, i64 %zext3
%11 = load ptr, ptr %10, align 8
%12 = call i32 (ptr, ...) @printf(ptr @.str.2, i32 %2, ptr %5, i32 %8, ptr %11)
ret void
Expand Down

0 comments on commit 70f906c

Please sign in to comment.