| ... | @@ -150,6 +150,13 @@ static TypeTableEntry *get_expr_type(AstNode *node) { | ... | @@ -150,6 +150,13 @@ static TypeTableEntry *get_expr_type(AstNode *node) { |
| 150 | return expr->type_entry; | 150 | return expr->type_entry; |
| 151 | } | 151 | } |
| 152 | | 152 | |
| | 153 | static bool handle_is_ptr(TypeTableEntry *type_entry) { |
| | 154 | return type_entry->id == TypeTableEntryIdStruct || |
| | 155 | (type_entry->id == TypeTableEntryIdEnum && type_entry->data.enumeration.gen_field_count != 0) || |
| | 156 | type_entry->id == TypeTableEntryIdMaybe || |
| | 157 | type_entry->id == TypeTableEntryIdArray; |
| | 158 | } |
| | 159 | |
| 153 | static LLVMValueRef gen_number_literal_raw(CodeGen *g, AstNode *source_node, | 160 | static LLVMValueRef gen_number_literal_raw(CodeGen *g, AstNode *source_node, |
| 154 | NumLitCodeGen *codegen_num_lit, AstNodeNumberLiteral *num_lit_node) | 161 | NumLitCodeGen *codegen_num_lit, AstNodeNumberLiteral *num_lit_node) |
| 155 | { | 162 | { |
| ... | @@ -681,12 +688,27 @@ static LLVMValueRef gen_slice_expr(CodeGen *g, AstNode *node) { | ... | @@ -681,12 +688,27 @@ static LLVMValueRef gen_slice_expr(CodeGen *g, AstNode *node) { |
| 681 | } | 688 | } |
| 682 | } | 689 | } |
| 683 | | 690 | |
| | 691 | |
| 684 | static LLVMValueRef gen_array_access_expr(CodeGen *g, AstNode *node, bool is_lvalue) { | 692 | static LLVMValueRef gen_array_access_expr(CodeGen *g, AstNode *node, bool is_lvalue) { |
| 685 | assert(node->type == NodeTypeArrayAccessExpr); | 693 | assert(node->type == NodeTypeArrayAccessExpr); |
| 686 | | 694 | |
| 687 | LLVMValueRef ptr = gen_array_ptr(g, node); | 695 | LLVMValueRef ptr = gen_array_ptr(g, node); |
| | 696 | TypeTableEntry *child_type; |
| | 697 | TypeTableEntry *array_type = get_expr_type(node->data.array_access_expr.array_ref_expr); |
| | 698 | if (array_type->id == TypeTableEntryIdPointer) { |
| | 699 | child_type = array_type->data.pointer.child_type; |
| | 700 | } else if (array_type->id == TypeTableEntryIdStruct) { |
| | 701 | assert(array_type->data.structure.is_unknown_size_array); |
| | 702 | TypeTableEntry *child_ptr_type = array_type->data.structure.fields[0].type_entry; |
| | 703 | assert(child_ptr_type->id == TypeTableEntryIdPointer); |
| | 704 | child_type = child_ptr_type->data.pointer.child_type; |
| | 705 | } else if (array_type->id == TypeTableEntryIdArray) { |
| | 706 | child_type = array_type->data.array.child_type; |
| | 707 | } else { |
| | 708 | zig_unreachable(); |
| | 709 | } |
| 688 | | 710 | |
| 689 | if (is_lvalue || !ptr) { | 711 | if (is_lvalue || !ptr || handle_is_ptr(child_type)) { |
| 690 | return ptr; | 712 | return ptr; |
| 691 | } else { | 713 | } else { |
| 692 | add_debug_source_node(g, node); | 714 | add_debug_source_node(g, node); |
| ... | @@ -1142,10 +1164,7 @@ static LLVMValueRef gen_bool_or_expr(CodeGen *g, AstNode *expr_node) { | ... | @@ -1142,10 +1164,7 @@ static LLVMValueRef gen_bool_or_expr(CodeGen *g, AstNode *expr_node) { |
| 1142 | static LLVMValueRef gen_struct_memcpy(CodeGen *g, AstNode *source_node, LLVMValueRef src, LLVMValueRef dest, | 1164 | static LLVMValueRef gen_struct_memcpy(CodeGen *g, AstNode *source_node, LLVMValueRef src, LLVMValueRef dest, |
| 1143 | TypeTableEntry *type_entry) | 1165 | TypeTableEntry *type_entry) |
| 1144 | { | 1166 | { |
| 1145 | assert(type_entry->id == TypeTableEntryIdStruct || | 1167 | assert(handle_is_ptr(type_entry)); |
| 1146 | type_entry->id == TypeTableEntryIdMaybe || | | |
| 1147 | (type_entry->id == TypeTableEntryIdEnum && type_entry->data.enumeration.gen_field_count != 0) || | | |
| 1148 | type_entry->id == TypeTableEntryIdArray); | | |
| 1149 | | 1168 | |
| 1150 | LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0); | 1169 | LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0); |
| 1151 | | 1170 | |
| ... | @@ -1168,11 +1187,7 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, AstNode *source_node, BinOpType b | ... | @@ -1168,11 +1187,7 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, AstNode *source_node, BinOpType b |
| 1168 | LLVMValueRef target_ref, LLVMValueRef value, | 1187 | LLVMValueRef target_ref, LLVMValueRef value, |
| 1169 | TypeTableEntry *op1_type, TypeTableEntry *op2_type) | 1188 | TypeTableEntry *op1_type, TypeTableEntry *op2_type) |
| 1170 | { | 1189 | { |
| 1171 | if (op1_type->id == TypeTableEntryIdStruct || | 1190 | if (handle_is_ptr(op1_type)) { |
| 1172 | (op1_type->id == TypeTableEntryIdEnum && op1_type->data.enumeration.gen_field_count != 0) || | | |
| 1173 | op1_type->id == TypeTableEntryIdMaybe || | | |
| 1174 | op1_type->id == TypeTableEntryIdArray) | | |
| 1175 | { | | |
| 1176 | assert(op1_type == op2_type); | 1191 | assert(op1_type == op2_type); |
| 1177 | assert(bin_op == BinOpTypeAssign); | 1192 | assert(bin_op == BinOpTypeAssign); |
| 1178 | | 1193 | |
| ... | @@ -1632,8 +1647,10 @@ static LLVMValueRef gen_container_init_expr(CodeGen *g, AstNode *node) { | ... | @@ -1632,8 +1647,10 @@ static LLVMValueRef gen_container_init_expr(CodeGen *g, AstNode *node) { |
| 1632 | | 1647 | |
| 1633 | add_debug_source_node(g, field_node); | 1648 | add_debug_source_node(g, field_node); |
| 1634 | LLVMValueRef field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, type_struct_field->gen_index, ""); | 1649 | LLVMValueRef field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, type_struct_field->gen_index, ""); |
| 1635 | LLVMValueRef value = gen_expr(g, field_node->data.struct_val_field.expr); | 1650 | AstNode *expr_node = field_node->data.struct_val_field.expr; |
| 1636 | LLVMBuildStore(g->builder, value, field_ptr); | 1651 | LLVMValueRef value = gen_expr(g, expr_node); |
| | 1652 | gen_assign_raw(g, field_node, BinOpTypeAssign, field_ptr, value, |
| | 1653 | type_struct_field->type_entry, get_expr_type(expr_node)); |
| 1637 | } | 1654 | } |
| 1638 | | 1655 | |
| 1639 | return tmp_struct_ptr; | 1656 | return tmp_struct_ptr; |
| ... | @@ -1651,6 +1668,8 @@ static LLVMValueRef gen_container_init_expr(CodeGen *g, AstNode *node) { | ... | @@ -1651,6 +1668,8 @@ static LLVMValueRef gen_container_init_expr(CodeGen *g, AstNode *node) { |
| 1651 | int field_count = type_entry->data.array.len; | 1668 | int field_count = type_entry->data.array.len; |
| 1652 | assert(field_count == node->data.container_init_expr.entries.length); | 1669 | assert(field_count == node->data.container_init_expr.entries.length); |
| 1653 | | 1670 | |
| | 1671 | TypeTableEntry *child_type = type_entry->data.array.child_type; |
| | 1672 | |
| 1654 | for (int i = 0; i < field_count; i += 1) { | 1673 | for (int i = 0; i < field_count; i += 1) { |
| 1655 | AstNode *field_node = node->data.container_init_expr.entries.at(i); | 1674 | AstNode *field_node = node->data.container_init_expr.entries.at(i); |
| 1656 | LLVMValueRef elem_val = gen_expr(g, field_node); | 1675 | LLVMValueRef elem_val = gen_expr(g, field_node); |
| ... | @@ -1661,7 +1680,8 @@ static LLVMValueRef gen_container_init_expr(CodeGen *g, AstNode *node) { | ... | @@ -1661,7 +1680,8 @@ static LLVMValueRef gen_container_init_expr(CodeGen *g, AstNode *node) { |
| 1661 | }; | 1680 | }; |
| 1662 | add_debug_source_node(g, field_node); | 1681 | add_debug_source_node(g, field_node); |
| 1663 | LLVMValueRef elem_ptr = LLVMBuildInBoundsGEP(g->builder, tmp_array_ptr, indices, 2, ""); | 1682 | LLVMValueRef elem_ptr = LLVMBuildInBoundsGEP(g->builder, tmp_array_ptr, indices, 2, ""); |
| 1664 | LLVMBuildStore(g->builder, elem_val, elem_ptr); | 1683 | gen_assign_raw(g, field_node, BinOpTypeAssign, elem_ptr, elem_val, |
| | 1684 | child_type, get_expr_type(field_node)); |
| 1665 | } | 1685 | } |
| 1666 | | 1686 | |
| 1667 | return tmp_array_ptr; | 1687 | return tmp_array_ptr; |