diff options
| author | Andrew Kelley <superjoe30@gmail.com> | 2016-12-22 09:35:07 -0500 |
|---|---|---|
| committer | Andrew Kelley <superjoe30@gmail.com> | 2016-12-22 09:35:07 -0500 |
| commit | ba8af0f1e281fc7e56a8f4eb6f3974efc6ed043d (patch) | |
| tree | 09dfe2192b5b5623dfb74f47303422fb2efee506 /src | |
| parent | ed962d9d21c451ed2e0ff125d6817f3c71827154 (diff) | |
| download | zig-ba8af0f1e281fc7e56a8f4eb6f3974efc6ed043d.tar.gz zig-ba8af0f1e281fc7e56a8f4eb6f3974efc6ed043d.zip | |
IR: fix missing implicit casts in init expressions
and implement runtime struct init instruction
Diffstat (limited to 'src')
| -rw-r--r-- | src/codegen.cpp | 18 | ||||
| -rw-r--r-- | src/ir.cpp | 45 |
2 files changed, 42 insertions, 21 deletions
diff --git a/src/codegen.cpp b/src/codegen.cpp index b28b370f9a..df5e6d1787 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -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(); } diff --git a/src/ir.cpp b/src/ir.cpp index 05427f75e8..99a80d6408 100644 --- a/src/ir.cpp +++ b/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); |
