Commit 47f58d6d02
Changed files (3)
doc/vim/syntax/zig.vim
@@ -25,7 +25,7 @@ syn keyword zigBoolean true false
syn match zigOperator display "\%(+%\?\|-%\?\|/\|*%\?\|=\|\^\|&\|?\||\|!\|>\|<\|%\|<<%\?\|>>\)=\?"
syn match zigArrowCharacter display "->"
-syn match zigDecNumber display "\<[0-9]*\%(.[0-9]\+\)\=\%([eE][+-]\?[0-9]\+\)\="
+syn match zigDecNumber display "\<[0-9]\+\%(.[0-9]\+\)\=\%([eE][+-]\?[0-9]\+\)\="
syn match zigHexNumber display "\<0x[a-fA-F0-9]\+\%(.[a-fA-F0-9]\+\%([pP][+-]\?[0-9]\+\)\?\)\="
syn match zigOctNumber display "\<0o[0-7]\+"
syn match zigBinNumber display "\<0b[01]\+\%(.[01]\+\%([eE][+-]\?[0-9]\+\)\?\)\="
src/codegen.cpp
@@ -849,16 +849,43 @@ static LLVMValueRef gen_struct_memcpy(CodeGen *g, LLVMValueRef src, LLVMValueRef
return LLVMBuildCall(g->builder, g->memcpy_fn_val, params, 5, "");
}
-static LLVMValueRef gen_assign_raw(CodeGen *g, LLVMValueRef target_ref, LLVMValueRef value,
- TypeTableEntry *child_type)
+static LLVMValueRef gen_assign_raw(CodeGen *g, LLVMValueRef ptr, TypeTableEntry *ptr_type,
+ LLVMValueRef value)
{
+ TypeTableEntry *child_type = get_underlying_type(ptr_type->data.pointer.child_type);
+
if (!type_has_bits(child_type))
return nullptr;
if (handle_is_ptr(child_type))
- return gen_struct_memcpy(g, value, target_ref, child_type);
+ return gen_struct_memcpy(g, value, ptr, child_type);
+
+ uint32_t unaligned_bit_count = ptr_type->data.pointer.unaligned_bit_count;
+ if (unaligned_bit_count == 0) {
+ LLVMValueRef llvm_instruction = LLVMBuildStore(g->builder, value, ptr);
+ LLVMSetVolatile(llvm_instruction, ptr_type->data.pointer.is_volatile);
+ return nullptr;
+ }
+
+ LLVMValueRef containing_int = LLVMBuildLoad(g->builder, ptr, "");
+
+ uint32_t bit_offset = ptr_type->data.pointer.bit_offset;
+ uint32_t host_bit_count = LLVMGetIntTypeWidth(LLVMTypeOf(containing_int));
+ uint32_t shift_amt = host_bit_count - bit_offset - unaligned_bit_count;
+ LLVMValueRef shift_amt_val = LLVMConstInt(LLVMTypeOf(containing_int), shift_amt, false);
+
+ LLVMValueRef mask_val = LLVMConstAllOnes(child_type->type_ref);
+ mask_val = LLVMConstZExt(mask_val, LLVMTypeOf(containing_int));
+ mask_val = LLVMConstShl(mask_val, shift_amt_val);
+ mask_val = LLVMConstNot(mask_val);
+
+ LLVMValueRef anded_containing_int = LLVMBuildAnd(g->builder, containing_int, mask_val, "");
+ LLVMValueRef extended_value = LLVMBuildZExt(g->builder, value, LLVMTypeOf(containing_int), "");
+ LLVMValueRef shifted_value = LLVMBuildShl(g->builder, extended_value, shift_amt_val, "");
+ LLVMValueRef ored_value = LLVMBuildOr(g->builder, shifted_value, anded_containing_int, "");
- LLVMBuildStore(g->builder, value, target_ref);
+ LLVMValueRef llvm_instruction = LLVMBuildStore(g->builder, ored_value, ptr);
+ LLVMSetVolatile(llvm_instruction, ptr_type->data.pointer.is_volatile);
return nullptr;
}
@@ -903,7 +930,7 @@ static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrIns
LLVMBuildRet(g->builder, by_val_value);
} else {
assert(g->cur_ret_ptr);
- gen_assign_raw(g, g->cur_ret_ptr, value, return_type);
+ gen_assign_raw(g, g->cur_ret_ptr, get_pointer_to_type(g, return_type, false), value);
LLVMBuildRetVoid(g->builder);
}
} else {
@@ -1549,7 +1576,8 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable,
if (have_init_expr) {
assert(var->value->type == init_value->value.type);
- gen_assign_raw(g, var->value_ref, ir_llvm_value(g, init_value), var->value->type);
+ gen_assign_raw(g, var->value_ref, get_pointer_to_type(g, var->value->type, false),
+ ir_llvm_value(g, init_value));
} else {
bool ignore_uninit = false;
// handle runtime stack allocation
@@ -1615,40 +1643,9 @@ static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, Ir
assert(instruction->ptr->value.type->id == TypeTableEntryIdPointer);
TypeTableEntry *ptr_type = get_underlying_type(instruction->ptr->value.type);
- TypeTableEntry *child_type = get_underlying_type(ptr_type->data.pointer.child_type);
- if (!type_has_bits(child_type))
- return nullptr;
+ gen_assign_raw(g, ptr, ptr_type, value);
- if (handle_is_ptr(child_type))
- return gen_struct_memcpy(g, value, ptr, child_type);
-
- uint32_t unaligned_bit_count = ptr_type->data.pointer.unaligned_bit_count;
- if (unaligned_bit_count == 0) {
- LLVMValueRef llvm_instruction = LLVMBuildStore(g->builder, value, ptr);
- LLVMSetVolatile(llvm_instruction, ptr_type->data.pointer.is_volatile);
- return nullptr;
- }
-
- LLVMValueRef containing_int = LLVMBuildLoad(g->builder, ptr, "");
-
- uint32_t bit_offset = ptr_type->data.pointer.bit_offset;
- uint32_t host_bit_count = LLVMGetIntTypeWidth(LLVMTypeOf(containing_int));
- uint32_t shift_amt = host_bit_count - bit_offset - unaligned_bit_count;
- LLVMValueRef shift_amt_val = LLVMConstInt(LLVMTypeOf(containing_int), shift_amt, false);
-
- LLVMValueRef mask_val = LLVMConstAllOnes(child_type->type_ref);
- mask_val = LLVMConstZExt(mask_val, LLVMTypeOf(containing_int));
- mask_val = LLVMConstShl(mask_val, shift_amt_val);
- mask_val = LLVMConstNot(mask_val);
-
- LLVMValueRef anded_containing_int = LLVMBuildAnd(g->builder, containing_int, mask_val, "");
- LLVMValueRef extended_value = LLVMBuildZExt(g->builder, value, LLVMTypeOf(containing_int), "");
- LLVMValueRef shifted_value = LLVMBuildShl(g->builder, extended_value, shift_amt_val, "");
- LLVMValueRef ored_value = LLVMBuildOr(g->builder, shifted_value, anded_containing_int, "");
-
- LLVMValueRef llvm_instruction = LLVMBuildStore(g->builder, ored_value, ptr);
- LLVMSetVolatile(llvm_instruction, ptr_type->data.pointer.is_volatile);
return nullptr;
}
@@ -2531,7 +2528,7 @@ static LLVMValueRef ir_render_maybe_wrap(CodeGen *g, IrExecutable *executable, I
LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, maybe_child_index, "");
// child_type and instruction->value->value.type may differ by constness
- gen_assign_raw(g, val_ptr, payload_val, child_type);
+ gen_assign_raw(g, val_ptr, get_pointer_to_type(g, child_type, false), payload_val);
LLVMValueRef maybe_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, maybe_null_index, "");
LLVMBuildStore(g->builder, LLVMConstAllOnes(LLVMInt1Type()), maybe_ptr);
@@ -2577,7 +2574,7 @@ static LLVMValueRef ir_render_err_wrap_payload(CodeGen *g, IrExecutable *executa
LLVMBuildStore(g->builder, ok_err_val, err_tag_ptr);
LLVMValueRef payload_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, err_union_payload_index, "");
- gen_assign_raw(g, payload_ptr, payload_val, child_type);
+ gen_assign_raw(g, payload_ptr, get_pointer_to_type(g, child_type, false), payload_val);
return instruction->tmp_ptr;
}
@@ -2617,7 +2614,7 @@ static LLVMValueRef ir_render_init_enum(CodeGen *g, IrExecutable *executable, Ir
LLVMValueRef bitcasted_union_field_ptr = LLVMBuildBitCast(g->builder, union_field_ptr,
LLVMPointerType(union_val_type->type_ref, 0), "");
- gen_assign_raw(g, bitcasted_union_field_ptr, new_union_val, union_val_type);
+ gen_assign_raw(g, bitcasted_union_field_ptr, get_pointer_to_type(g, union_val_type, false), new_union_val);
}
return tmp_struct_ptr;
@@ -2632,7 +2629,12 @@ static LLVMValueRef ir_render_struct_init(CodeGen *g, IrExecutable *executable,
LLVMValueRef field_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, type_struct_field->gen_index, "");
LLVMValueRef value = ir_llvm_value(g, field->value);
- gen_assign_raw(g, field_ptr, value, type_struct_field->type_entry);
+
+ TypeTableEntry *ptr_type = get_pointer_to_type_extra(g, type_struct_field->type_entry,
+ false, false,
+ type_struct_field->packed_bits_offset, type_struct_field->unaligned_bit_count);
+
+ gen_assign_raw(g, field_ptr, ptr_type, value);
}
return instruction->tmp_ptr;
}
@@ -2655,7 +2657,7 @@ static LLVMValueRef ir_render_container_init_list(CodeGen *g, IrExecutable *exec
LLVMConstInt(g->builtin_types.entry_usize->type_ref, i, false),
};
LLVMValueRef elem_ptr = LLVMBuildInBoundsGEP(g->builder, tmp_array_ptr, indices, 2, "");
- gen_assign_raw(g, elem_ptr, elem_val, child_type);
+ gen_assign_raw(g, elem_ptr, get_pointer_to_type(g, child_type, false), elem_val);
}
return tmp_array_ptr;
test/cases/struct.zig
@@ -361,3 +361,25 @@ test "alignedArrayOfPackedStruct" {
assert(ptr.a[1].a == 0xbb);
assert(ptr.a[1].b == 0xbb);
}
+
+
+
+test "runtime struct initialization of bitfield" {
+ const s1 = Nibbles { .x = x1, .y = x1 };
+ const s2 = Nibbles { .x = u4(x2), .y = u4(x2) };
+
+ assert(s1.x == x1);
+ assert(s1.y == x1);
+ assert(s2.x == u4(x2));
+ assert(s2.y == u4(x2));
+}
+
+const u4 = @intType(false, 4);
+
+var x1 = u4(1);
+var x2 = u8(2);
+
+const Nibbles = packed struct {
+ x: u4,
+ y: u4,
+};