diff --git a/src/all_types.hpp b/src/all_types.hpp index a5b0804985..ebccbaa37f 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -1263,6 +1263,7 @@ struct TypeStructField { uint32_t bit_offset_in_host; // offset from the memory at gen_index uint32_t host_int_bytes; // size of host integer uint32_t align; + bool is_comptime; }; enum ResolveStatus { diff --git a/src/analyze.cpp b/src/analyze.cpp index c3e24ecb46..37c93c638a 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -2788,6 +2788,9 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { type_struct_field->src_index = i; type_struct_field->gen_index = SIZE_MAX; + if (type_struct_field->is_comptime) + continue; + switch (type_val_resolve_requires_comptime(g, field_type_val)) { case ReqCompTimeYes: struct_type->data.structure.requires_comptime = true; @@ -7987,8 +7990,9 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS // inserting padding bytes where LLVM would do it automatically. size_t llvm_struct_abi_align = 0; for (size_t i = 0; i < field_count; i += 1) { - ZigType *field_type = struct_type->data.structure.fields[i]->type_entry; - if (!type_has_bits(field_type)) + TypeStructField *field = struct_type->data.structure.fields[i]; + ZigType *field_type = field->type_entry; + if (field->is_comptime || !type_has_bits(field_type)) continue; LLVMTypeRef field_llvm_type = get_llvm_type(g, field_type); size_t llvm_field_abi_align = LLVMABIAlignmentOfType(g->target_data_ref, field_llvm_type); @@ -7999,7 +8003,7 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS TypeStructField *field = struct_type->data.structure.fields[i]; ZigType *field_type = field->type_entry; - if (!type_has_bits(field_type)) { + if (field->is_comptime || !type_has_bits(field_type)) { field->gen_index = SIZE_MAX; continue; } diff --git a/src/ir.cpp b/src/ir.cpp index 9b99fed42c..5f398bb11a 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -655,6 +655,10 @@ static ZigValue *const_ptr_pointee_unchecked(CodeGen *g, ZigValue *const_val) { if (isf != nullptr) { TypeStructField *field = find_struct_type_field(isf->inferred_struct_type, isf->field_name); assert(field != nullptr); + if (field->is_comptime) { + assert(field->init_val != nullptr); + return field->init_val; + } assert(const_val->data.x_ptr.special == ConstPtrSpecialRef); ZigValue *struct_val = const_val->data.x_ptr.data.ref.pointee; return struct_val->data.x_struct.fields[field->src_index]; @@ -17373,6 +17377,13 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source field->type_val = create_const_type(ira->codegen, field->type_entry); field->src_index = old_field_count; field->decl_node = uncasted_value->source_node; + if (instr_is_comptime(uncasted_value)) { + ZigValue *uncasted_val = ir_resolve_const(ira, uncasted_value, UndefOk); + field->is_comptime = true; + field->init_val = create_const_vals(1); + copy_const_val(field->init_val, uncasted_val); + return ir_const_void(ira, source_instr); + } ZigType *struct_ptr_type = get_pointer_to_type(ira->codegen, isf->inferred_struct_type, false); IrInstruction *casted_ptr; @@ -19510,6 +19521,11 @@ static IrInstruction *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInstruction ZigType *field_type = resolve_struct_field_type(ira->codegen, field); if (field_type == nullptr) return ira->codegen->invalid_instruction; + if (field->is_comptime) { + IrInstruction *elem = ir_const(ira, source_instr, field_type); + copy_const_val(elem->value, field->init_val); + return ir_get_ref(ira, source_instr, elem, true, false); + } switch (type_has_one_possible_value(ira->codegen, field_type)) { case OnePossibleValueInvalid: return ira->codegen->invalid_instruction; @@ -21716,6 +21732,10 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira, for (size_t i = 0; i < const_ptrs.length; i += 1) { IrInstruction *elem_result_loc = const_ptrs.at(i); assert(elem_result_loc->value->special == ConstValSpecialStatic); + if (elem_result_loc->value->type->data.pointer.inferred_struct_field != nullptr) { + // This field will be generated comptime; no need to do this. + continue; + } IrInstruction *deref = ir_get_deref(ira, elem_result_loc, elem_result_loc, nullptr); elem_result_loc->value->special = ConstValSpecialRuntime; ir_analyze_store_ptr(ira, elem_result_loc, elem_result_loc, deref, false); diff --git a/test/stage1/behavior/call.zig b/test/stage1/behavior/call.zig index d68fb64d02..1280224fa3 100644 --- a/test/stage1/behavior/call.zig +++ b/test/stage1/behavior/call.zig @@ -37,12 +37,12 @@ test "tuple parameters" { comptime expect(@call(.{}, add, .{ 12, 34 }) == 46); { const separate_args0 = .{ a, b }; - //TODO const separate_args1 = .{ a, 34 }; + const separate_args1 = .{ a, 34 }; const separate_args2 = .{ 12, 34 }; - //TODO const separate_args3 = .{ 12, b }; + const separate_args3 = .{ 12, b }; expect(@call(.{ .modifier = .always_inline }, add, separate_args0) == 46); - // TODO expect(@call(.{ .modifier = .always_inline }, add, separate_args1) == 46); + expect(@call(.{ .modifier = .always_inline }, add, separate_args1) == 46); expect(@call(.{ .modifier = .always_inline }, add, separate_args2) == 46); - // TODO expect(@call(.{ .modifier = .always_inline }, add, separate_args3) == 46); + expect(@call(.{ .modifier = .always_inline }, add, separate_args3) == 46); } } diff --git a/test/stage1/behavior/struct.zig b/test/stage1/behavior/struct.zig index 408f5da687..8ac14583c5 100644 --- a/test/stage1/behavior/struct.zig +++ b/test/stage1/behavior/struct.zig @@ -775,8 +775,6 @@ test "anonymous struct literal assigned to variable" { expect(vec.@"0" == 22); expect(vec.@"1" == 55); expect(vec.@"2" == 99); - vec.@"1" += 1; - expect(vec.@"1" == 56); } test "struct with var field" {