mirror of
https://github.com/ziglang/zig.git
synced 2025-12-18 12:13:20 +00:00
implement comptime struct fields
This commit is contained in:
parent
19c1b5a33a
commit
119ed128c0
@ -1263,6 +1263,7 @@ struct TypeStructField {
|
|||||||
uint32_t bit_offset_in_host; // offset from the memory at gen_index
|
uint32_t bit_offset_in_host; // offset from the memory at gen_index
|
||||||
uint32_t host_int_bytes; // size of host integer
|
uint32_t host_int_bytes; // size of host integer
|
||||||
uint32_t align;
|
uint32_t align;
|
||||||
|
bool is_comptime;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ResolveStatus {
|
enum ResolveStatus {
|
||||||
|
|||||||
@ -2788,6 +2788,9 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {
|
|||||||
type_struct_field->src_index = i;
|
type_struct_field->src_index = i;
|
||||||
type_struct_field->gen_index = SIZE_MAX;
|
type_struct_field->gen_index = SIZE_MAX;
|
||||||
|
|
||||||
|
if (type_struct_field->is_comptime)
|
||||||
|
continue;
|
||||||
|
|
||||||
switch (type_val_resolve_requires_comptime(g, field_type_val)) {
|
switch (type_val_resolve_requires_comptime(g, field_type_val)) {
|
||||||
case ReqCompTimeYes:
|
case ReqCompTimeYes:
|
||||||
struct_type->data.structure.requires_comptime = true;
|
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.
|
// inserting padding bytes where LLVM would do it automatically.
|
||||||
size_t llvm_struct_abi_align = 0;
|
size_t llvm_struct_abi_align = 0;
|
||||||
for (size_t i = 0; i < field_count; i += 1) {
|
for (size_t i = 0; i < field_count; i += 1) {
|
||||||
ZigType *field_type = struct_type->data.structure.fields[i]->type_entry;
|
TypeStructField *field = struct_type->data.structure.fields[i];
|
||||||
if (!type_has_bits(field_type))
|
ZigType *field_type = field->type_entry;
|
||||||
|
if (field->is_comptime || !type_has_bits(field_type))
|
||||||
continue;
|
continue;
|
||||||
LLVMTypeRef field_llvm_type = get_llvm_type(g, field_type);
|
LLVMTypeRef field_llvm_type = get_llvm_type(g, field_type);
|
||||||
size_t llvm_field_abi_align = LLVMABIAlignmentOfType(g->target_data_ref, field_llvm_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];
|
TypeStructField *field = struct_type->data.structure.fields[i];
|
||||||
ZigType *field_type = field->type_entry;
|
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;
|
field->gen_index = SIZE_MAX;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
20
src/ir.cpp
20
src/ir.cpp
@ -655,6 +655,10 @@ static ZigValue *const_ptr_pointee_unchecked(CodeGen *g, ZigValue *const_val) {
|
|||||||
if (isf != nullptr) {
|
if (isf != nullptr) {
|
||||||
TypeStructField *field = find_struct_type_field(isf->inferred_struct_type, isf->field_name);
|
TypeStructField *field = find_struct_type_field(isf->inferred_struct_type, isf->field_name);
|
||||||
assert(field != nullptr);
|
assert(field != nullptr);
|
||||||
|
if (field->is_comptime) {
|
||||||
|
assert(field->init_val != nullptr);
|
||||||
|
return field->init_val;
|
||||||
|
}
|
||||||
assert(const_val->data.x_ptr.special == ConstPtrSpecialRef);
|
assert(const_val->data.x_ptr.special == ConstPtrSpecialRef);
|
||||||
ZigValue *struct_val = const_val->data.x_ptr.data.ref.pointee;
|
ZigValue *struct_val = const_val->data.x_ptr.data.ref.pointee;
|
||||||
return struct_val->data.x_struct.fields[field->src_index];
|
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->type_val = create_const_type(ira->codegen, field->type_entry);
|
||||||
field->src_index = old_field_count;
|
field->src_index = old_field_count;
|
||||||
field->decl_node = uncasted_value->source_node;
|
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);
|
ZigType *struct_ptr_type = get_pointer_to_type(ira->codegen, isf->inferred_struct_type, false);
|
||||||
IrInstruction *casted_ptr;
|
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);
|
ZigType *field_type = resolve_struct_field_type(ira->codegen, field);
|
||||||
if (field_type == nullptr)
|
if (field_type == nullptr)
|
||||||
return ira->codegen->invalid_instruction;
|
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)) {
|
switch (type_has_one_possible_value(ira->codegen, field_type)) {
|
||||||
case OnePossibleValueInvalid:
|
case OnePossibleValueInvalid:
|
||||||
return ira->codegen->invalid_instruction;
|
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) {
|
for (size_t i = 0; i < const_ptrs.length; i += 1) {
|
||||||
IrInstruction *elem_result_loc = const_ptrs.at(i);
|
IrInstruction *elem_result_loc = const_ptrs.at(i);
|
||||||
assert(elem_result_loc->value->special == ConstValSpecialStatic);
|
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);
|
IrInstruction *deref = ir_get_deref(ira, elem_result_loc, elem_result_loc, nullptr);
|
||||||
elem_result_loc->value->special = ConstValSpecialRuntime;
|
elem_result_loc->value->special = ConstValSpecialRuntime;
|
||||||
ir_analyze_store_ptr(ira, elem_result_loc, elem_result_loc, deref, false);
|
ir_analyze_store_ptr(ira, elem_result_loc, elem_result_loc, deref, false);
|
||||||
|
|||||||
@ -37,12 +37,12 @@ test "tuple parameters" {
|
|||||||
comptime expect(@call(.{}, add, .{ 12, 34 }) == 46);
|
comptime expect(@call(.{}, add, .{ 12, 34 }) == 46);
|
||||||
{
|
{
|
||||||
const separate_args0 = .{ a, b };
|
const separate_args0 = .{ a, b };
|
||||||
//TODO const separate_args1 = .{ a, 34 };
|
const separate_args1 = .{ a, 34 };
|
||||||
const separate_args2 = .{ 12, 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);
|
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);
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -775,8 +775,6 @@ test "anonymous struct literal assigned to variable" {
|
|||||||
expect(vec.@"0" == 22);
|
expect(vec.@"0" == 22);
|
||||||
expect(vec.@"1" == 55);
|
expect(vec.@"1" == 55);
|
||||||
expect(vec.@"2" == 99);
|
expect(vec.@"2" == 99);
|
||||||
vec.@"1" += 1;
|
|
||||||
expect(vec.@"1" == 56);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
test "struct with var field" {
|
test "struct with var field" {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user