parent
10dbc735fe
commit
47f58d6d02
@ -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]\+\)\?\)\="
|
||||
|
@ -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);
|
||||
|
||||
LLVMBuildStore(g->builder, value, target_ref);
|
||||
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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
@ -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,
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user