authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-10-15 17:58:26-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-10-15 18:00:16-04:00
log9050cd847a2a767df34bc3e0bbc9c789b8a49a91
tree297aa589cd56f83773336b359519879e8c001f6e
parent7495fd8cb9eea3d571ec62eff069b443ac0e3a6a
signaturelock-open Commit is signed but in an unrecognized format.

fix non-byte-aligned packed struct field...

...passed as generic fn parameter causing invalid LLVM IR. closes #3460

3 files changed, 44 insertions(+), 2 deletions(-)

src/analyze.cpp+11
...@@ -8602,6 +8602,9 @@ static void resolve_llvm_types_fn_type(CodeGen *g, ZigType *fn_type) {...@@ -8602,6 +8602,9 @@ static void resolve_llvm_types_fn_type(CodeGen *g, ZigType *fn_type) {
8602 fn_type->llvm_di_type = ZigLLVMCreateDebugPointerType(g->dbuilder, fn_type->data.fn.raw_di_type,8602 fn_type->llvm_di_type = ZigLLVMCreateDebugPointerType(g->dbuilder, fn_type->data.fn.raw_di_type,
8603 LLVMStoreSizeOfType(g->target_data_ref, fn_type->llvm_type),8603 LLVMStoreSizeOfType(g->target_data_ref, fn_type->llvm_type),
8604 LLVMABIAlignmentOfType(g->target_data_ref, fn_type->llvm_type), "");8604 LLVMABIAlignmentOfType(g->target_data_ref, fn_type->llvm_type), "");
8605
8606 gen_param_types.deinit();
8607 param_di_types.deinit();
8605}8608}
86068609
8607void resolve_llvm_types_fn(CodeGen *g, ZigFn *fn) {8610void resolve_llvm_types_fn(CodeGen *g, ZigFn *fn) {
...@@ -8636,6 +8639,9 @@ void resolve_llvm_types_fn(CodeGen *g, ZigFn *fn) {...@@ -8636,6 +8639,9 @@ void resolve_llvm_types_fn(CodeGen *g, ZigFn *fn) {
8636 fn->raw_type_ref = LLVMFunctionType(get_llvm_type(g, gen_return_type),8639 fn->raw_type_ref = LLVMFunctionType(get_llvm_type(g, gen_return_type),
8637 gen_param_types.items, gen_param_types.length, false);8640 gen_param_types.items, gen_param_types.length, false);
8638 fn->raw_di_type = ZigLLVMCreateSubroutineType(g->dbuilder, param_di_types.items, (int)param_di_types.length, 0);8641 fn->raw_di_type = ZigLLVMCreateSubroutineType(g->dbuilder, param_di_types.items, (int)param_di_types.length, 0);
8642
8643 param_di_types.deinit();
8644 gen_param_types.deinit();
8639}8645}
86408646
8641static void resolve_llvm_types_anyerror(CodeGen *g) {8647static void resolve_llvm_types_anyerror(CodeGen *g) {
...@@ -8660,6 +8666,8 @@ static void resolve_llvm_types_anyerror(CodeGen *g) {...@@ -8660,6 +8666,8 @@ static void resolve_llvm_types_anyerror(CodeGen *g) {
8660 tag_debug_align_in_bits,8666 tag_debug_align_in_bits,
8661 err_enumerators.items, err_enumerators.length,8667 err_enumerators.items, err_enumerators.length,
8662 get_llvm_di_type(g, g->err_tag_type), "");8668 get_llvm_di_type(g, g->err_tag_type), "");
8669
8670 err_enumerators.deinit();
8663}8671}
86648672
8665static void resolve_llvm_types_async_frame(CodeGen *g, ZigType *frame_type, ResolveStatus wanted_resolve_status) {8673static void resolve_llvm_types_async_frame(CodeGen *g, ZigType *frame_type, ResolveStatus wanted_resolve_status) {
...@@ -8805,6 +8813,9 @@ static void resolve_llvm_types_any_frame(CodeGen *g, ZigType *any_frame_type, Re...@@ -8805,6 +8813,9 @@ static void resolve_llvm_types_any_frame(CodeGen *g, ZigType *any_frame_type, Re
8805 nullptr, di_element_types.items, di_element_types.length, 0, nullptr, "");8813 nullptr, di_element_types.items, di_element_types.length, 0, nullptr, "");
88068814
8807 ZigLLVMReplaceTemporary(g->dbuilder, frame_header_di_type, replacement_di_type);8815 ZigLLVMReplaceTemporary(g->dbuilder, frame_header_di_type, replacement_di_type);
8816
8817 field_types.deinit();
8818 di_element_types.deinit();
8808}8819}
88098820
8810static void resolve_llvm_types(CodeGen *g, ZigType *type, ResolveStatus wanted_resolve_status) {8821static void resolve_llvm_types(CodeGen *g, ZigType *type, ResolveStatus wanted_resolve_status) {
src/codegen.cpp+13-2
...@@ -4245,8 +4245,19 @@ static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutable *executa...@@ -4245,8 +4245,19 @@ static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutable *executa
4245 if ((err = type_resolve(g, struct_type, ResolveStatusLLVMFull)))4245 if ((err = type_resolve(g, struct_type, ResolveStatusLLVMFull)))
4246 codegen_report_errors_and_exit(g);4246 codegen_report_errors_and_exit(g);
42474247
4248 assert(field->gen_index != SIZE_MAX);4248 src_assert(field->gen_index != SIZE_MAX, instruction->base.source_node);
4249 return LLVMBuildStructGEP(g->builder, struct_ptr, (unsigned)field->gen_index, "");4249 LLVMValueRef field_ptr_val = LLVMBuildStructGEP(g->builder, struct_ptr, (unsigned)field->gen_index, "");
4250 ZigType *res_type = instruction->base.value.type;
4251 src_assert(res_type->id == ZigTypeIdPointer, instruction->base.source_node);
4252 if (res_type->data.pointer.host_int_bytes != 0) {
4253 // We generate packed structs with get_llvm_type_of_n_bytes, which is
4254 // u8 for 1 byte or [n]u8 for multiple bytes. But the pointer to the type
4255 // is supposed to be a pointer to the integer. So we bitcast it here.
4256 LLVMTypeRef int_elem_type = LLVMIntType(8*res_type->data.pointer.host_int_bytes);
4257 LLVMTypeRef integer_ptr_type = LLVMPointerType(int_elem_type, 0);
4258 return LLVMBuildBitCast(g->builder, field_ptr_val, integer_ptr_type, "");
4259 }
4260 return field_ptr_val;
4250}4261}
42514262
4252static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executable,4263static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executable,
test/stage1/behavior/struct.zig+20
...@@ -689,3 +689,23 @@ test "non-packed struct with u128 entry in union" {...@@ -689,3 +689,23 @@ test "non-packed struct with u128 entry in union" {
689 s.f2 = v2;689 s.f2 = v2;
690 std.testing.expect(s.f2.Num == 123);690 std.testing.expect(s.f2.Num == 123);
691}691}
692
693test "packed struct field passed to generic function" {
694 const S = struct {
695 const P = packed struct {
696 b: u5,
697 g: u5,
698 r: u5,
699 a: u1,
700 };
701
702 fn genericReadPackedField(ptr: var) u5 {
703 return ptr.*;
704 }
705 };
706
707 var p: S.P = undefined;
708 p.b = 29;
709 var loaded = S.genericReadPackedField(&p.b);
710 expect(loaded == 29);
711}