IR: fix missing implicit casts in init expressions
and implement runtime struct init instructionmaster
parent
ed962d9d21
commit
ba8af0f1e2
|
@ -2171,6 +2171,20 @@ static LLVMValueRef ir_render_init_enum(CodeGen *g, IrExecutable *executable, Ir
|
|||
return tmp_struct_ptr;
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_struct_init(CodeGen *g, IrExecutable *executable, IrInstructionStructInit *instruction) {
|
||||
for (size_t i = 0; i < instruction->field_count; i += 1) {
|
||||
IrInstructionStructInitField *field = &instruction->fields[i];
|
||||
TypeStructField *type_struct_field = field->type_struct_field;
|
||||
if (!type_has_bits(type_struct_field->type_entry))
|
||||
continue;
|
||||
|
||||
LLVMValueRef field_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, type_struct_field->gen_index, "");
|
||||
LLVMValueRef value = ir_llvm_value(g, field->value);
|
||||
gen_assign_raw(g, field_ptr, value, type_struct_field->type_entry, type_struct_field->type_entry);
|
||||
}
|
||||
return instruction->tmp_ptr;
|
||||
}
|
||||
|
||||
static void set_debug_location(CodeGen *g, IrInstruction *instruction) {
|
||||
AstNode *source_node = instruction->source_node;
|
||||
Scope *scope = instruction->scope;
|
||||
|
@ -2307,12 +2321,12 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
|
|||
return ir_render_enum_tag(g, executable, (IrInstructionEnumTag *)instruction);
|
||||
case IrInstructionIdInitEnum:
|
||||
return ir_render_init_enum(g, executable, (IrInstructionInitEnum *)instruction);
|
||||
case IrInstructionIdStructInit:
|
||||
return ir_render_struct_init(g, executable, (IrInstructionStructInit *)instruction);
|
||||
case IrInstructionIdSwitchVar:
|
||||
zig_panic("TODO render switch var instruction to LLVM");
|
||||
case IrInstructionIdContainerInitList:
|
||||
zig_panic("TODO render container init list instruction to LLVM");
|
||||
case IrInstructionIdStructInit:
|
||||
zig_panic("TODO render struct init to LLVM");
|
||||
}
|
||||
zig_unreachable();
|
||||
}
|
||||
|
|
45
src/ir.cpp
45
src/ir.cpp
|
@ -8431,8 +8431,7 @@ static TypeTableEntry *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstru
|
|||
|
||||
IrInstructionStructInitField *new_fields = allocate<IrInstructionStructInitField>(actual_field_count);
|
||||
|
||||
FnTableEntry *fn_entry = exec_fn_entry(ira->new_irb.exec);
|
||||
bool outside_fn = (fn_entry == nullptr);
|
||||
bool is_comptime = ir_should_inline(&ira->new_irb);
|
||||
|
||||
ConstExprValue const_val = {};
|
||||
const_val.special = ConstValSpecialStatic;
|
||||
|
@ -8456,6 +8455,10 @@ static TypeTableEntry *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstru
|
|||
if (type_field->type_entry->id == TypeTableEntryIdInvalid)
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
|
||||
IrInstruction *casted_field_value = ir_implicit_cast(ira, field_value, type_field->type_entry);
|
||||
if (casted_field_value == ira->codegen->invalid_instruction)
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
|
||||
size_t field_index = type_field->src_index;
|
||||
AstNode *existing_assign_node = field_assign_nodes[field_index];
|
||||
if (existing_assign_node) {
|
||||
|
@ -8465,19 +8468,19 @@ static TypeTableEntry *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstru
|
|||
}
|
||||
field_assign_nodes[field_index] = field->source_node;
|
||||
|
||||
new_fields[field_index].value = field_value;
|
||||
new_fields[field_index].value = casted_field_value;
|
||||
new_fields[field_index].type_struct_field = type_field;
|
||||
|
||||
if (const_val.special == ConstValSpecialStatic) {
|
||||
if (outside_fn || field_value->static_value.special != ConstValSpecialRuntime) {
|
||||
ConstExprValue *field_val = ir_resolve_const(ira, field_value, UndefOk);
|
||||
if (is_comptime || casted_field_value->static_value.special != ConstValSpecialRuntime) {
|
||||
ConstExprValue *field_val = ir_resolve_const(ira, casted_field_value, UndefOk);
|
||||
if (!field_val)
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
|
||||
const_val.data.x_struct.fields[field_index] = *field_val;
|
||||
const_val.depends_on_compile_var = const_val.depends_on_compile_var || field_val->depends_on_compile_var;
|
||||
} else {
|
||||
first_non_const_instruction = field_value;
|
||||
first_non_const_instruction = casted_field_value;
|
||||
const_val.special = ConstValSpecialRuntime;
|
||||
}
|
||||
}
|
||||
|
@ -8500,7 +8503,7 @@ static TypeTableEntry *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstru
|
|||
return container_type;
|
||||
}
|
||||
|
||||
if (outside_fn) {
|
||||
if (is_comptime) {
|
||||
ir_add_error_node(ira, first_non_const_instruction->source_node,
|
||||
buf_sprintf("unable to evaluate constant expression"));
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
|
@ -8513,7 +8516,9 @@ static TypeTableEntry *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstru
|
|||
return container_type;
|
||||
}
|
||||
|
||||
static TypeTableEntry *ir_analyze_instruction_container_init_list(IrAnalyze *ira, IrInstructionContainerInitList *instruction) {
|
||||
static TypeTableEntry *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
|
||||
IrInstructionContainerInitList *instruction)
|
||||
{
|
||||
IrInstruction *container_type_value = instruction->container_type->other;
|
||||
if (container_type_value->type_entry->id == TypeTableEntryIdInvalid)
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
|
@ -8527,7 +8532,8 @@ static TypeTableEntry *ir_analyze_instruction_container_init_list(IrAnalyze *ira
|
|||
bool depends_on_compile_var = container_type_value->static_value.depends_on_compile_var;
|
||||
|
||||
if (container_type->id == TypeTableEntryIdStruct && !is_slice(container_type) && elem_count == 0) {
|
||||
return ir_analyze_container_init_fields(ira, &instruction->base, container_type, 0, nullptr, depends_on_compile_var);
|
||||
return ir_analyze_container_init_fields(ira, &instruction->base, container_type,
|
||||
0, nullptr, depends_on_compile_var);
|
||||
} else if (is_slice(container_type)) {
|
||||
TypeTableEntry *pointer_type = container_type->data.structure.fields[slice_ptr_index].type_entry;
|
||||
assert(pointer_type->id == TypeTableEntryIdPointer);
|
||||
|
@ -8539,8 +8545,7 @@ static TypeTableEntry *ir_analyze_instruction_container_init_list(IrAnalyze *ira
|
|||
const_val.data.x_array.elements = allocate<ConstExprValue>(elem_count);
|
||||
const_val.data.x_array.size = elem_count;
|
||||
|
||||
FnTableEntry *fn_entry = exec_fn_entry(ira->new_irb.exec);
|
||||
bool outside_fn = (fn_entry == nullptr);
|
||||
bool is_comptime = ir_should_inline(&ira->new_irb);
|
||||
|
||||
IrInstruction **new_items = allocate<IrInstruction *>(elem_count);
|
||||
|
||||
|
@ -8551,18 +8556,22 @@ static TypeTableEntry *ir_analyze_instruction_container_init_list(IrAnalyze *ira
|
|||
if (arg_value->type_entry->id == TypeTableEntryIdInvalid)
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
|
||||
new_items[i] = arg_value;
|
||||
IrInstruction *casted_arg = ir_implicit_cast(ira, arg_value, child_type);
|
||||
if (casted_arg == ira->codegen->invalid_instruction)
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
|
||||
new_items[i] = casted_arg;
|
||||
|
||||
if (const_val.special == ConstValSpecialStatic) {
|
||||
if (outside_fn || arg_value->static_value.special != ConstValSpecialRuntime) {
|
||||
ConstExprValue *elem_val = ir_resolve_const(ira, arg_value, UndefBad);
|
||||
if (is_comptime || casted_arg->static_value.special != ConstValSpecialRuntime) {
|
||||
ConstExprValue *elem_val = ir_resolve_const(ira, casted_arg, UndefBad);
|
||||
if (!elem_val)
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
|
||||
const_val.data.x_array.elements[i] = *elem_val;
|
||||
const_val.depends_on_compile_var = const_val.depends_on_compile_var || elem_val->depends_on_compile_var;
|
||||
} else {
|
||||
first_non_const_instruction = arg_value;
|
||||
first_non_const_instruction = casted_arg;
|
||||
const_val.special = ConstValSpecialRuntime;
|
||||
}
|
||||
}
|
||||
|
@ -8575,7 +8584,7 @@ static TypeTableEntry *ir_analyze_instruction_container_init_list(IrAnalyze *ira
|
|||
return fixed_size_array_type;
|
||||
}
|
||||
|
||||
if (outside_fn) {
|
||||
if (is_comptime) {
|
||||
ir_add_error_node(ira, first_non_const_instruction->source_node,
|
||||
buf_sprintf("unable to evaluate constant expression"));
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
|
@ -8602,10 +8611,8 @@ static TypeTableEntry *ir_analyze_instruction_container_init_list(IrAnalyze *ira
|
|||
return ira->codegen->builtin_types.entry_invalid;
|
||||
}
|
||||
} else if (container_type_value->type_entry->id == TypeTableEntryIdEnumTag) {
|
||||
// TODO I wrote this commit message when I had some sake
|
||||
// might be worth re-examining sober
|
||||
if (elem_count != 1) {
|
||||
ir_add_error(ira, &instruction->base, buf_sprintf("expected 1 elment"));
|
||||
ir_add_error(ira, &instruction->base, buf_sprintf("enum initialization requires exactly one element"));
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
}
|
||||
ConstExprValue *tag_value = ir_resolve_const(ira, container_type_value, UndefBad);
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
const assert = @import("std").debug.assert;
|
||||
|
||||
struct Node {
|
||||
const Node = struct {
|
||||
payload: i32,
|
||||
children: []Node,
|
||||
}
|
||||
};
|
||||
|
||||
fn structContainsSliceOfItself() {
|
||||
@setFnTest(this, true);
|
||||
@setFnTest(this);
|
||||
|
||||
var nodes = []Node {
|
||||
Node {
|
||||
|
@ -42,3 +40,9 @@ fn structContainsSliceOfItself() {
|
|||
assert(root.children[2].children[0].payload == 31);
|
||||
assert(root.children[2].children[1].payload == 32);
|
||||
}
|
||||
|
||||
// TODO const assert = @import("std").debug.assert;
|
||||
fn assert(ok: bool) {
|
||||
if (!ok)
|
||||
@unreachable();
|
||||
}
|
|
@ -20,3 +20,4 @@ const test_struct = @import("cases3/struct.zig");
|
|||
const test_switch = @import("cases3/switch.zig");
|
||||
const test_this = @import("cases3/this.zig");
|
||||
const test_while = @import("cases3/while.zig");
|
||||
const test_struct_contains_slice_of_itself = @import("cases3/struct_contains_slice_of_itself.zig");
|
||||
|
|
Loading…
Reference in New Issue