diff --git a/releasenotes.md b/releasenotes.md index 338c51601..b23b0b255 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -29,6 +29,7 @@ - Use `weak_odr` rather than `weak` on Windows which seems to prevent issues such as #1704. - Use `weak` on dyn-symbols on Linux. - Fix crash on project.json not having an empty set of targets. +- Miscompile when indexing an array with small unsigned types for enums. ### Stdlib changes - Increase BitWriter.write_bits limit up to 32 bits. diff --git a/src/compiler/llvm_codegen_expr.c b/src/compiler/llvm_codegen_expr.c index f8a27327c..b6592a67d 100644 --- a/src/compiler/llvm_codegen_expr.c +++ b/src/compiler/llvm_codegen_expr.c @@ -5292,10 +5292,9 @@ LLVMValueRef llvm_emit_array_gep_raw_index(GenContext *c, LLVMValueRef ptr, LLVM LLVMTypeRef element_type = LLVMGetElementType(array_type); Type *index_type = index->type; ASSERT0(type_is_integer(index_type)); - LLVMTypeRef idx_type = llvm_get_type(c, index_type); if (type_is_unsigned(index_type) && type_size(index_type) < type_size(type_usz)) { - index_val = llvm_zext_trunc(c, index_val, idx_type); + index_val = llvm_zext_trunc(c, index_val, llvm_get_type(c, type_usz)); } *alignment = type_min_alignment(llvm_abi_size(c, element_type), array_alignment); return llvm_emit_pointer_inbounds_gep_raw(c, element_type, ptr, index_val); diff --git a/test/test_suite/enumerations/enum_associated_value.c3t b/test/test_suite/enumerations/enum_associated_value.c3t index 508ca6e50..5c5054874 100644 --- a/test/test_suite/enumerations/enum_associated_value.c3t +++ b/test/test_suite/enumerations/enum_associated_value.c3t @@ -41,17 +41,21 @@ entry: store i32 1, ptr %f, align 4 store i32 0, ptr %g, align 4 %0 = load i32, ptr %f, align 4 - %ptroffset = getelementptr inbounds [4 x i8], ptr @"test.Foo$val", i32 %0 + %zext = zext i32 %0 to i64 + %ptroffset = getelementptr inbounds [4 x i8], ptr @"test.Foo$val", i64 %zext %1 = load i32, ptr %f, align 4 - %ptroffset1 = getelementptr inbounds [8 x i8], ptr @"test.Foo$testme", i32 %1 + %zext1 = zext i32 %1 to i64 + %ptroffset2 = getelementptr inbounds [8 x i8], ptr @"test.Foo$testme", i64 %zext1 %2 = load i32, ptr %g, align 4 - %ptroffset2 = getelementptr inbounds [4 x i8], ptr @"test.Foo$val", i32 %2 + %zext3 = zext i32 %2 to i64 + %ptroffset4 = getelementptr inbounds [4 x i8], ptr @"test.Foo$val", i64 %zext3 %3 = load i32, ptr %g, align 4 - %ptroffset3 = getelementptr inbounds [8 x i8], ptr @"test.Foo$testme", i32 %3 + %zext5 = zext i32 %3 to i64 + %ptroffset6 = getelementptr inbounds [8 x i8], ptr @"test.Foo$testme", i64 %zext5 %4 = load i32, ptr %ptroffset, align 4 - %5 = load ptr, ptr %ptroffset1, align 8 - %6 = load i32, ptr %ptroffset2, align 4 - %7 = load ptr, ptr %ptroffset3, align 8 + %5 = load ptr, ptr %ptroffset2, align 8 + %6 = load i32, ptr %ptroffset4, align 4 + %7 = load ptr, ptr %ptroffset6, align 8 %8 = call i32 (ptr, ...) @printf(ptr @.str.2, i32 %4, ptr %5, i32 %6, ptr %7) ret void }