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) {
86028602 fn_type->llvm_di_type = ZigLLVMCreateDebugPointerType(g->dbuilder, fn_type->data.fn.raw_di_type,
86038603 LLVMStoreSizeOfType(g->target_data_ref, fn_type->llvm_type),
86048604 LLVMABIAlignmentOfType(g->target_data_ref, fn_type->llvm_type), "");
8605
8606 gen_param_types.deinit();
8607 param_di_types.deinit();
86058608}
86068609
86078610void resolve_llvm_types_fn(CodeGen *g, ZigFn *fn) {
......@@ -8636,6 +8639,9 @@ void resolve_llvm_types_fn(CodeGen *g, ZigFn *fn) {
86368639 fn->raw_type_ref = LLVMFunctionType(get_llvm_type(g, gen_return_type),
86378640 gen_param_types.items, gen_param_types.length, false);
86388641 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();
86398645}
86408646
86418647static void resolve_llvm_types_anyerror(CodeGen *g) {
......@@ -8660,6 +8666,8 @@ static void resolve_llvm_types_anyerror(CodeGen *g) {
86608666 tag_debug_align_in_bits,
86618667 err_enumerators.items, err_enumerators.length,
86628668 get_llvm_di_type(g, g->err_tag_type), "");
8669
8670 err_enumerators.deinit();
86638671}
86648672
86658673static 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
88058813 nullptr, di_element_types.items, di_element_types.length, 0, nullptr, "");
88068814
88078815 ZigLLVMReplaceTemporary(g->dbuilder, frame_header_di_type, replacement_di_type);
8816
8817 field_types.deinit();
8818 di_element_types.deinit();
88088819}
88098820
88108821static 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
42454245 if ((err = type_resolve(g, struct_type, ResolveStatusLLVMFull)))
42464246 codegen_report_errors_and_exit(g);
42474247
4248 assert(field->gen_index != SIZE_MAX);
4249 return LLVMBuildStructGEP(g->builder, struct_ptr, (unsigned)field->gen_index, "");
4248 src_assert(field->gen_index != SIZE_MAX, instruction->base.source_node);
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;
42504261}
42514262
42524263static 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" {
689689 s.f2 = v2;
690690 std.testing.expect(s.f2.Num == 123);
691691}
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}