fix: handle full-width bit_field literal masks

This commit is contained in:
bymehul
2026-03-10 23:21:19 +05:30
parent 7a41092dcc
commit c9e55d3add
3 changed files with 35 additions and 15 deletions

View File

@@ -1,5 +1,14 @@
gb_internal lbValue lb_emit_arith_matrix(lbProcedure *p, TokenKind op, lbValue lhs, lbValue rhs, Type *type, bool component_wise);
gb_internal LLVMValueRef lb_const_low_bits_mask(LLVMTypeRef type, u64 bit_count) {
GB_ASSERT(bit_count <= 64);
if (bit_count == 0) {
return LLVMConstInt(type, 0, false);
}
u64 mask = bit_count == 64 ? ~0ull : (1ull<<bit_count)-1;
return LLVMConstInt(type, mask, false);
}
gb_internal lbValue lb_emit_logical_binary_expr(lbProcedure *p, TokenKind op, Ast *left, Ast *right, Type *final_type) {
lbModule *m = p->module;
@@ -5148,13 +5157,7 @@ gb_internal lbAddr lb_build_addr_compound_lit(lbProcedure *p, Ast *expr) {
for (isize i = 0; i < fields.count; i++) {
auto const &f = fields[i];
LLVMValueRef mask = LLVMConstInt(lit, 1, false);
#if LLVM_VERSION_MAJOR >= 19
mask = LLVMBuildShl(p->builder, mask, LLVMConstInt(lit, f.bit_size, false), "");
#else
mask = LLVMConstShl(mask, LLVMConstInt(lit, f.bit_size, false));
#endif
mask = LLVMConstSub(mask, LLVMConstInt(lit, 1, false));
LLVMValueRef mask = lb_const_low_bits_mask(lit, f.bit_size);
LLVMValueRef elem = values[i].value;
if (lb_sizeof(lit) < lb_sizeof(LLVMTypeOf(elem))) {
@@ -5200,13 +5203,7 @@ gb_internal lbAddr lb_build_addr_compound_lit(lbProcedure *p, Ast *expr) {
GB_ASSERT(mask_width > 0);
bits_to_set -= mask_width;
LLVMValueRef mask = LLVMConstInt(vt, 1, false);
#if LLVM_VERSION_MAJOR >= 19
mask = LLVMBuildShl(p->builder, mask, LLVMConstInt(vt, mask_width, false), "");
#else
mask = LLVMConstShl(mask, LLVMConstInt(vt, mask_width, false));
#endif
mask = LLVMConstSub(mask, LLVMConstInt(vt, 1, false));
LLVMValueRef mask = lb_const_low_bits_mask(vt, mask_width);
LLVMValueRef to_set = LLVMBuildAnd(p->builder, val, mask, "");
@@ -6076,4 +6073,3 @@ gb_internal lbAddr lb_build_addr_internal(lbProcedure *p, Ast *expr) {
return {};
}

View File

@@ -36,6 +36,7 @@ $ODIN test ../test_issue_5699.odin $COMMON
$ODIN test ../test_issue_6068.odin $COMMON
$ODIN test ../test_issue_6101.odin $COMMON
$ODIN test ../test_issue_6165.odin $COMMON
$ODIN test ../test_issue_6396.odin $COMMON
if [[ $($ODIN build ../test_issue_6240.odin $COMMON 2>&1 >/dev/null | grep -c "Error:") -eq 3 ]] ; then
echo "SUCCESSFUL 1/1"
else

View File

@@ -0,0 +1,23 @@
// Tests issue #6396 https://github.com/odin-lang/Odin/issues/6396
package test_issues
import "core:testing"
Issue6396_Full_Width_Field :: bit_field u32 {
a: u32 | 32,
}
@test
test_issue_6396_full_width_bit_field_literal :: proc(t: ^testing.T) {
f0: Issue6396_Full_Width_Field = {a = 7}
testing.expect_value(t, f0.a, u32(7))
f0 = {a = 3}
testing.expect_value(t, f0.a, u32(3))
f0 = Issue6396_Full_Width_Field{a = 11}
testing.expect_value(t, f0.a, u32(11))
f0.a = 12
testing.expect_value(t, f0.a, u32(12))
}