diff options
| author | gingerBill <bill@gingerbill.org> | 2019-12-27 15:53:35 +0000 |
|---|---|---|
| committer | gingerBill <bill@gingerbill.org> | 2019-12-27 15:53:35 +0000 |
| commit | c2b3056094ab00d1e609053c6bf7fd1c2609098f (patch) | |
| tree | c88170d840127820cf9409612b3caa5b903cf95d /src/ir.cpp | |
| parent | f99f351e01dc8140a36c1a9b5568f5081cfa1e70 (diff) | |
Fix enumerated array compound literals IR
Diffstat (limited to 'src/ir.cpp')
| -rw-r--r-- | src/ir.cpp | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/src/ir.cpp b/src/ir.cpp index 05d946691..2b912cf8a 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -8448,6 +8448,109 @@ irAddr ir_build_addr(irProcedure *proc, Ast *expr) { } break; } + case Type_EnumeratedArray: { + if (cl->elems.count > 0) { + ir_emit_store(proc, v, ir_add_module_constant(proc->module, type, exact_value_compound(expr))); + + auto temp_data = array_make<irCompoundLitElemTempData>(heap_allocator(), 0, cl->elems.count); + defer (array_free(&temp_data)); + + // NOTE(bill): Separate value, gep, store into their own chunks + for_array(i, cl->elems) { + Ast *elem = cl->elems[i]; + if (elem->kind == Ast_FieldValue) { + ast_node(fv, FieldValue, elem); + if (ir_is_elem_const(proc->module, fv->value, et)) { + continue; + } + if (is_ast_range(fv->field)) { + ast_node(ie, BinaryExpr, fv->field); + TypeAndValue lo_tav = ie->left->tav; + TypeAndValue hi_tav = ie->right->tav; + GB_ASSERT(lo_tav.mode == Addressing_Constant); + GB_ASSERT(hi_tav.mode == Addressing_Constant); + + TokenKind op = ie->op.kind; + i64 lo = exact_value_to_i64(lo_tav.value); + i64 hi = exact_value_to_i64(hi_tav.value); + if (op == Token_Ellipsis) { + hi += 1; + } + + irValue *value = ir_build_expr(proc, fv->value); + + for (i64 k = lo; k < hi; k++) { + irCompoundLitElemTempData data = {}; + data.value = value; + data.elem_index = cast(i32)k; + array_add(&temp_data, data); + } + + } else { + auto tav = fv->field->tav; + GB_ASSERT(tav.mode == Addressing_Constant); + i64 index = exact_value_to_i64(tav.value); + + irCompoundLitElemTempData data = {}; + data.value = ir_emit_conv(proc, ir_build_expr(proc, fv->value), et); + data.expr = fv->value; + data.elem_index = cast(i32)index; + array_add(&temp_data, data); + } + + } else { + if (ir_is_elem_const(proc->module, elem, et)) { + continue; + } + irCompoundLitElemTempData data = {}; + data.expr = elem; + data.elem_index = cast(i32)i; + array_add(&temp_data, data); + } + } + + + i32 index_offset = cast(i32)exact_value_to_i64(bt->EnumeratedArray.min_value); + + for_array(i, temp_data) { + i32 index = temp_data[i].elem_index - index_offset; + temp_data[i].gep = ir_emit_array_epi(proc, v, index); + } + + for_array(i, temp_data) { + auto return_ptr_hint_ast = proc->return_ptr_hint_ast; + auto return_ptr_hint_value = proc->return_ptr_hint_value; + auto return_ptr_hint_used = proc->return_ptr_hint_used; + defer (proc->return_ptr_hint_ast = return_ptr_hint_ast); + defer (proc->return_ptr_hint_value = return_ptr_hint_value); + defer (proc->return_ptr_hint_used = return_ptr_hint_used); + + irValue *field_expr = temp_data[i].value; + Ast *expr = temp_data[i].expr; + + proc->return_ptr_hint_value = temp_data[i].gep; + proc->return_ptr_hint_ast = unparen_expr(expr); + + if (field_expr == nullptr) { + field_expr = ir_build_expr(proc, expr); + } + Type *t = ir_type(field_expr); + GB_ASSERT(t->kind != Type_Tuple); + irValue *ev = ir_emit_conv(proc, field_expr, et); + + if (!proc->return_ptr_hint_used) { + temp_data[i].value = ev; + } + } + + for_array(i, temp_data) { + if (temp_data[i].value != nullptr) { + ir_emit_store(proc, temp_data[i].gep, temp_data[i].value, false); + } + } + } + break; + } case Type_Slice: { if (cl->elems.count > 0) { Type *elem_type = bt->Slice.elem; |