diff options
Diffstat (limited to 'src/ssa.cpp')
| -rw-r--r-- | src/ssa.cpp | 322 |
1 files changed, 167 insertions, 155 deletions
diff --git a/src/ssa.cpp b/src/ssa.cpp index 6d0969e46..060be979c 100644 --- a/src/ssa.cpp +++ b/src/ssa.cpp @@ -811,7 +811,7 @@ ssaValue *ssa_make_instr_array_element_ptr(ssaProcedure *p, ssaValue *address, s Type *t = ssa_type(address); GB_ASSERT(is_type_pointer(t)); t = base_type(type_deref(t)); - GB_ASSERT(is_type_array(t)); + GB_ASSERT(is_type_array(t) || is_type_vector(t)); Type *result_type = make_type_pointer(p->module->allocator, t->Array.elem); @@ -1524,7 +1524,7 @@ ssaValue *ssa_emit_comp(ssaProcedure *proc, TokenKind op_kind, ssaValue *left, s ssaValue *ssa_emit_array_ep(ssaProcedure *proc, ssaValue *s, ssaValue *index) { Type *st = base_type(type_deref(ssa_type(s))); - GB_ASSERT(is_type_array(st)); + GB_ASSERT(is_type_array(st) || is_type_vector(st)); // NOTE(bill): For some weird legacy reason in LLVM, structure elements must be accessed as an i32 index = ssa_emit_conv(proc, index, t_i32); @@ -1693,6 +1693,8 @@ ssaValue *ssa_emit_deep_field_gep(ssaProcedure *proc, Type *type, ssaValue *e, S } } else if (type->kind == Type_Slice) { e = ssa_emit_struct_ep(proc, e, index); + } else if (type->kind == Type_Vector) { + e = ssa_emit_array_ep(proc, e, index); } else { GB_PANIC("un-gep-able type"); } @@ -1854,9 +1856,11 @@ String lookup_polymorphic_field(CheckerInfo *info, Type *dst, Type *src) { return f->token.string; } } - String name = lookup_polymorphic_field(info, dst, f->type); - if (name.len > 0) { - return name; + if (is_type_struct(f->type)) { + String name = lookup_polymorphic_field(info, dst, f->type); + if (name.len > 0) { + return name; + } } } } @@ -2673,156 +2677,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue case_ast_node(cl, CompoundLit, expr); - ssa_emit_comment(proc, make_string("CompoundLit")); - Type *type = type_of_expr(proc->module->info, expr); - Type *bt = base_type(type); - ssaValue *v = ssa_add_local_generated(proc, type); - - Type *et = NULL; - switch (bt->kind) { - case Type_Vector: et = bt->Vector.elem; break; - case Type_Array: et = bt->Array.elem; break; - case Type_Slice: et = bt->Slice.elem; break; - } - - auto is_elem_const = [](ssaModule *m, AstNode *elem, Type *elem_type) -> b32 { - if (base_type(elem_type) == t_any) { - return false; - } - if (elem->kind == AstNode_FieldValue) { - elem = elem->FieldValue.value; - } - TypeAndValue *tav = type_and_value_of_expression(m->info, elem); - GB_ASSERT(tav != NULL); - return tav->value.kind != ExactValue_Invalid; - }; - - switch (bt->kind) { - default: GB_PANIC("Unknown CompoundLit type: %s", type_to_string(type)); break; - - case Type_Vector: { - ssaValue *result = ssa_add_module_constant(proc->module, type, make_exact_value_compound(expr)); - for_array(index, cl->elems) { - AstNode *elem = cl->elems[index]; - if (is_elem_const(proc->module, elem, et)) { - continue; - } - ssaValue *field_elem = ssa_build_expr(proc, elem); - Type *t = ssa_type(field_elem); - GB_ASSERT(t->kind != Type_Tuple); - ssaValue *ev = ssa_emit_conv(proc, field_elem, et); - ssaValue *i = ssa_make_const_int(proc->module->allocator, index); - result = ssa_emit(proc, ssa_make_instr_insert_element(proc, result, ev, i)); - } - - if (cl->elems.count == 1 && bt->Vector.count > 1) { - isize index_count = bt->Vector.count; - i32 *indices = gb_alloc_array(proc->module->allocator, i32, index_count); - for (isize i = 0; i < index_count; i++) { - indices[i] = 0; - } - ssaValue *sv = ssa_emit(proc, ssa_make_instr_vector_shuffle(proc, result, indices, index_count)); - ssa_emit_store(proc, v, sv); - return ssa_emit_load(proc, v); - } - return result; - } break; - - case Type_Record: { - GB_ASSERT(is_type_struct(bt)); - auto *st = &bt->Record; - if (cl->elems.count > 0) { - ssa_emit_store(proc, v, ssa_add_module_constant(proc->module, type, make_exact_value_compound(expr))); - for_array(field_index, cl->elems) { - AstNode *elem = cl->elems[field_index]; - - ssaValue *field_expr = NULL; - Entity *field = NULL; - isize index = field_index; - - if (elem->kind == AstNode_FieldValue) { - ast_node(fv, FieldValue, elem); - Selection sel = lookup_field(proc->module->allocator, bt, fv->field->Ident.string, false); - index = sel.index[0]; - elem = fv->value; - } else { - TypeAndValue *tav = type_and_value_of_expression(proc->module->info, elem); - Selection sel = lookup_field(proc->module->allocator, bt, st->fields_in_src_order[field_index]->token.string, false); - index = sel.index[0]; - } - - field = st->fields[index]; - if (is_elem_const(proc->module, elem, field->type)) { - continue; - } - - field_expr = ssa_build_expr(proc, elem); - - GB_ASSERT(ssa_type(field_expr)->kind != Type_Tuple); - - - - Type *ft = field->type; - ssaValue *fv = ssa_emit_conv(proc, field_expr, ft); - ssaValue *gep = ssa_emit_struct_ep(proc, v, index); - ssa_emit_store(proc, gep, fv); - } - } - } break; - case Type_Array: { - if (cl->elems.count > 0) { - ssa_emit_store(proc, v, ssa_add_module_constant(proc->module, type, make_exact_value_compound(expr))); - for_array(i, cl->elems) { - AstNode *elem = cl->elems[i]; - if (is_elem_const(proc->module, elem, et)) { - continue; - } - ssaValue *field_expr = ssa_build_expr(proc, elem); - Type *t = ssa_type(field_expr); - GB_ASSERT(t->kind != Type_Tuple); - ssaValue *ev = ssa_emit_conv(proc, field_expr, et); - ssaValue *gep = ssa_emit_array_ep(proc, v, i); - ssa_emit_store(proc, gep, ev); - } - } - } break; - case Type_Slice: { - if (cl->elems.count > 0) { - Type *elem_type = bt->Slice.elem; - Type *elem_ptr_type = make_type_pointer(proc->module->allocator, elem_type); - Type *elem_ptr_ptr_type = make_type_pointer(proc->module->allocator, elem_ptr_type); - Type *t_int_ptr = make_type_pointer(proc->module->allocator, t_int); - ssaValue *slice = ssa_add_module_constant(proc->module, type, make_exact_value_compound(expr)); - GB_ASSERT(slice->kind == ssaValue_ConstantSlice); - - ssaValue *data = ssa_emit_array_ep(proc, slice->ConstantSlice.backing_array, v_zero32); - - for_array(i, cl->elems) { - AstNode *elem = cl->elems[i]; - if (is_elem_const(proc->module, elem, et)) { - continue; - } - - ssaValue *field_expr = ssa_build_expr(proc, elem); - Type *t = ssa_type(field_expr); - GB_ASSERT(t->kind != Type_Tuple); - ssaValue *ev = ssa_emit_conv(proc, field_expr, elem_type); - ssaValue *offset = ssa_emit_ptr_offset(proc, data, ssa_make_const_int(proc->module->allocator, i)); - ssa_emit_store(proc, offset, ev); - } - - ssaValue *gep0 = ssa_emit_struct_ep(proc, v, 0); - ssaValue *gep1 = ssa_emit_struct_ep(proc, v, 1); - ssaValue *gep2 = ssa_emit_struct_ep(proc, v, 1); - - ssa_emit_store(proc, gep0, data); - ssa_emit_store(proc, gep1, ssa_make_const_int(proc->module->allocator, slice->ConstantSlice.count)); - ssa_emit_store(proc, gep2, ssa_make_const_int(proc->module->allocator, slice->ConstantSlice.count)); - } - } break; - } - - return ssa_emit_load(proc, v); + return ssa_emit_load(proc, ssa_build_addr(proc, expr).addr); case_end; @@ -3630,6 +3485,160 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) { ssa_emit_store(proc, v, e); return ssa_make_addr(v, expr); case_end; + + + case_ast_node(cl, CompoundLit, expr); + ssa_emit_comment(proc, make_string("CompoundLit")); + Type *type = type_of_expr(proc->module->info, expr); + Type *bt = base_type(type); + ssaValue *v = ssa_add_local_generated(proc, type); + + Type *et = NULL; + switch (bt->kind) { + case Type_Vector: et = bt->Vector.elem; break; + case Type_Array: et = bt->Array.elem; break; + case Type_Slice: et = bt->Slice.elem; break; + } + + auto is_elem_const = [](ssaModule *m, AstNode *elem, Type *elem_type) -> b32 { + if (base_type(elem_type) == t_any) { + return false; + } + if (elem->kind == AstNode_FieldValue) { + elem = elem->FieldValue.value; + } + TypeAndValue *tav = type_and_value_of_expression(m->info, elem); + GB_ASSERT(tav != NULL); + return tav->value.kind != ExactValue_Invalid; + }; + + switch (bt->kind) { + default: GB_PANIC("Unknown CompoundLit type: %s", type_to_string(type)); break; + + case Type_Vector: { + ssaValue *result = ssa_add_module_constant(proc->module, type, make_exact_value_compound(expr)); + for_array(index, cl->elems) { + AstNode *elem = cl->elems[index]; + if (is_elem_const(proc->module, elem, et)) { + continue; + } + ssaValue *field_elem = ssa_build_expr(proc, elem); + Type *t = ssa_type(field_elem); + GB_ASSERT(t->kind != Type_Tuple); + ssaValue *ev = ssa_emit_conv(proc, field_elem, et); + ssaValue *i = ssa_make_const_int(proc->module->allocator, index); + result = ssa_emit(proc, ssa_make_instr_insert_element(proc, result, ev, i)); + } + + if (cl->elems.count == 1 && bt->Vector.count > 1) { + isize index_count = bt->Vector.count; + i32 *indices = gb_alloc_array(proc->module->allocator, i32, index_count); + for (isize i = 0; i < index_count; i++) { + indices[i] = 0; + } + ssaValue *sv = ssa_emit(proc, ssa_make_instr_vector_shuffle(proc, result, indices, index_count)); + ssa_emit_store(proc, v, sv); + return ssa_make_addr(v, expr); + } + ssa_emit_store(proc, v, result); + } break; + + case Type_Record: { + GB_ASSERT(is_type_struct(bt)); + auto *st = &bt->Record; + if (cl->elems.count > 0) { + ssa_emit_store(proc, v, ssa_add_module_constant(proc->module, type, make_exact_value_compound(expr))); + for_array(field_index, cl->elems) { + AstNode *elem = cl->elems[field_index]; + + ssaValue *field_expr = NULL; + Entity *field = NULL; + isize index = field_index; + + if (elem->kind == AstNode_FieldValue) { + ast_node(fv, FieldValue, elem); + Selection sel = lookup_field(proc->module->allocator, bt, fv->field->Ident.string, false); + index = sel.index[0]; + elem = fv->value; + } else { + TypeAndValue *tav = type_and_value_of_expression(proc->module->info, elem); + Selection sel = lookup_field(proc->module->allocator, bt, st->fields_in_src_order[field_index]->token.string, false); + index = sel.index[0]; + } + + field = st->fields[index]; + if (is_elem_const(proc->module, elem, field->type)) { + continue; + } + + field_expr = ssa_build_expr(proc, elem); + + GB_ASSERT(ssa_type(field_expr)->kind != Type_Tuple); + + Type *ft = field->type; + ssaValue *fv = ssa_emit_conv(proc, field_expr, ft); + ssaValue *gep = ssa_emit_struct_ep(proc, v, index); + ssa_emit_store(proc, gep, fv); + } + } + } break; + case Type_Array: { + if (cl->elems.count > 0) { + ssa_emit_store(proc, v, ssa_add_module_constant(proc->module, type, make_exact_value_compound(expr))); + for_array(i, cl->elems) { + AstNode *elem = cl->elems[i]; + if (is_elem_const(proc->module, elem, et)) { + continue; + } + ssaValue *field_expr = ssa_build_expr(proc, elem); + Type *t = ssa_type(field_expr); + GB_ASSERT(t->kind != Type_Tuple); + ssaValue *ev = ssa_emit_conv(proc, field_expr, et); + ssaValue *gep = ssa_emit_array_ep(proc, v, i); + ssa_emit_store(proc, gep, ev); + } + } + } break; + case Type_Slice: { + if (cl->elems.count > 0) { + Type *elem_type = bt->Slice.elem; + Type *elem_ptr_type = make_type_pointer(proc->module->allocator, elem_type); + Type *elem_ptr_ptr_type = make_type_pointer(proc->module->allocator, elem_ptr_type); + Type *t_int_ptr = make_type_pointer(proc->module->allocator, t_int); + ssaValue *slice = ssa_add_module_constant(proc->module, type, make_exact_value_compound(expr)); + GB_ASSERT(slice->kind == ssaValue_ConstantSlice); + + ssaValue *data = ssa_emit_array_ep(proc, slice->ConstantSlice.backing_array, v_zero32); + + for_array(i, cl->elems) { + AstNode *elem = cl->elems[i]; + if (is_elem_const(proc->module, elem, et)) { + continue; + } + + ssaValue *field_expr = ssa_build_expr(proc, elem); + Type *t = ssa_type(field_expr); + GB_ASSERT(t->kind != Type_Tuple); + ssaValue *ev = ssa_emit_conv(proc, field_expr, elem_type); + ssaValue *offset = ssa_emit_ptr_offset(proc, data, ssa_make_const_int(proc->module->allocator, i)); + ssa_emit_store(proc, offset, ev); + } + + ssaValue *gep0 = ssa_emit_struct_ep(proc, v, 0); + ssaValue *gep1 = ssa_emit_struct_ep(proc, v, 1); + ssaValue *gep2 = ssa_emit_struct_ep(proc, v, 1); + + ssa_emit_store(proc, gep0, data); + ssa_emit_store(proc, gep1, ssa_make_const_int(proc->module->allocator, slice->ConstantSlice.count)); + ssa_emit_store(proc, gep2, ssa_make_const_int(proc->module->allocator, slice->ConstantSlice.count)); + } + } break; + } + + return ssa_make_addr(v, expr); + case_end; + + } TokenPos token_pos = ast_node_token(expr).pos; @@ -3777,6 +3786,9 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { for_array(i, inits) { + if (lvals[i].addr == NULL) { + continue; + } ssaValue *v = ssa_emit_conv(proc, inits[i], ssa_addr_type(lvals[i])); ssa_addr_store(proc, lvals[i], v); } |