diff --git a/src/analyze.cpp b/src/analyze.cpp index 399966d041..92b221a2ec 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -8602,6 +8602,9 @@ static void resolve_llvm_types_fn_type(CodeGen *g, ZigType *fn_type) { fn_type->llvm_di_type = ZigLLVMCreateDebugPointerType(g->dbuilder, fn_type->data.fn.raw_di_type, LLVMStoreSizeOfType(g->target_data_ref, fn_type->llvm_type), LLVMABIAlignmentOfType(g->target_data_ref, fn_type->llvm_type), ""); + + gen_param_types.deinit(); + param_di_types.deinit(); } void resolve_llvm_types_fn(CodeGen *g, ZigFn *fn) { @@ -8636,6 +8639,9 @@ void resolve_llvm_types_fn(CodeGen *g, ZigFn *fn) { fn->raw_type_ref = LLVMFunctionType(get_llvm_type(g, gen_return_type), gen_param_types.items, gen_param_types.length, false); fn->raw_di_type = ZigLLVMCreateSubroutineType(g->dbuilder, param_di_types.items, (int)param_di_types.length, 0); + + param_di_types.deinit(); + gen_param_types.deinit(); } static void resolve_llvm_types_anyerror(CodeGen *g) { @@ -8660,6 +8666,8 @@ static void resolve_llvm_types_anyerror(CodeGen *g) { tag_debug_align_in_bits, err_enumerators.items, err_enumerators.length, get_llvm_di_type(g, g->err_tag_type), ""); + + err_enumerators.deinit(); } static 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 nullptr, di_element_types.items, di_element_types.length, 0, nullptr, ""); ZigLLVMReplaceTemporary(g->dbuilder, frame_header_di_type, replacement_di_type); + + field_types.deinit(); + di_element_types.deinit(); } static void resolve_llvm_types(CodeGen *g, ZigType *type, ResolveStatus wanted_resolve_status) { diff --git a/src/codegen.cpp b/src/codegen.cpp index 4cdf22b1eb..f313c6cd1c 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -4245,8 +4245,19 @@ static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutable *executa if ((err = type_resolve(g, struct_type, ResolveStatusLLVMFull))) codegen_report_errors_and_exit(g); - assert(field->gen_index != SIZE_MAX); - return LLVMBuildStructGEP(g->builder, struct_ptr, (unsigned)field->gen_index, ""); + src_assert(field->gen_index != SIZE_MAX, instruction->base.source_node); + LLVMValueRef field_ptr_val = LLVMBuildStructGEP(g->builder, struct_ptr, (unsigned)field->gen_index, ""); + ZigType *res_type = instruction->base.value.type; + src_assert(res_type->id == ZigTypeIdPointer, instruction->base.source_node); + if (res_type->data.pointer.host_int_bytes != 0) { + // We generate packed structs with get_llvm_type_of_n_bytes, which is + // u8 for 1 byte or [n]u8 for multiple bytes. But the pointer to the type + // is supposed to be a pointer to the integer. So we bitcast it here. + LLVMTypeRef int_elem_type = LLVMIntType(8*res_type->data.pointer.host_int_bytes); + LLVMTypeRef integer_ptr_type = LLVMPointerType(int_elem_type, 0); + return LLVMBuildBitCast(g->builder, field_ptr_val, integer_ptr_type, ""); + } + return field_ptr_val; } static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executable, diff --git a/test/stage1/behavior/struct.zig b/test/stage1/behavior/struct.zig index c0dc580c36..ede31c0162 100644 --- a/test/stage1/behavior/struct.zig +++ b/test/stage1/behavior/struct.zig @@ -689,3 +689,23 @@ test "non-packed struct with u128 entry in union" { s.f2 = v2; std.testing.expect(s.f2.Num == 123); } + +test "packed struct field passed to generic function" { + const S = struct { + const P = packed struct { + b: u5, + g: u5, + r: u5, + a: u1, + }; + + fn genericReadPackedField(ptr: var) u5 { + return ptr.*; + } + }; + + var p: S.P = undefined; + p.b = 29; + var loaded = S.genericReadPackedField(&p.b); + expect(loaded == 29); +}