| ... | @@ -1725,84 +1725,91 @@ static LLVMValueRef gen_var_decl_raw(CodeGen *g, AstNode *source_node, AstNodeVa | ... | @@ -1725,84 +1725,91 @@ static LLVMValueRef gen_var_decl_raw(CodeGen *g, AstNode *source_node, AstNodeVa |
| 1725 | } | 1725 | } |
| 1726 | if (variable->type->size_in_bits == 0) { | 1726 | if (variable->type->size_in_bits == 0) { |
| 1727 | return nullptr; | 1727 | return nullptr; |
| 1728 | } else { | 1728 | } |
| 1729 | if (var_decl->expr) { | 1729 | |
| 1730 | TypeTableEntry *expr_type = get_expr_type(var_decl->expr); | 1730 | bool have_init_expr = false; |
| 1731 | LLVMValueRef value; | 1731 | if (var_decl->expr) { |
| 1732 | if (unwrap_maybe) { | 1732 | ConstExprValue *const_val = &get_resolved_expr(var_decl->expr)->const_val; |
| 1733 | assert(var_decl->expr); | 1733 | if (!const_val->ok || !const_val->undef) { |
| 1734 | assert(expr_type->id == TypeTableEntryIdMaybe); | 1734 | have_init_expr = true; |
| 1735 | value = gen_unwrap_maybe(g, source_node, *init_value); | 1735 | } |
| 1736 | expr_type = expr_type->data.maybe.child_type; | 1736 | } |
| 1737 | } else { | 1737 | if (have_init_expr) { |
| 1738 | value = *init_value; | 1738 | TypeTableEntry *expr_type = get_expr_type(var_decl->expr); |
| 1739 | } | 1739 | LLVMValueRef value; |
| 1740 | gen_assign_raw(g, var_decl->expr, BinOpTypeAssign, variable->value_ref, | 1740 | if (unwrap_maybe) { |
| 1741 | value, variable->type, expr_type); | 1741 | assert(var_decl->expr); |
| | 1742 | assert(expr_type->id == TypeTableEntryIdMaybe); |
| | 1743 | value = gen_unwrap_maybe(g, source_node, *init_value); |
| | 1744 | expr_type = expr_type->data.maybe.child_type; |
| 1742 | } else { | 1745 | } else { |
| 1743 | bool ignore_uninit = false; | 1746 | value = *init_value; |
| 1744 | TypeTableEntry *var_type = get_type_for_type_node(var_decl->type); | 1747 | } |
| 1745 | if (var_type->id == TypeTableEntryIdStruct && | 1748 | gen_assign_raw(g, var_decl->expr, BinOpTypeAssign, variable->value_ref, |
| 1746 | var_type->data.structure.is_unknown_size_array) | 1749 | value, variable->type, expr_type); |
| 1747 | { | 1750 | } else { |
| 1748 | assert(var_decl->type->type == NodeTypeArrayType); | 1751 | bool ignore_uninit = false; |
| 1749 | AstNode *size_node = var_decl->type->data.array_type.size; | 1752 | TypeTableEntry *var_type = get_type_for_type_node(var_decl->type); |
| 1750 | if (size_node) { | 1753 | if (var_type->id == TypeTableEntryIdStruct && |
| 1751 | ConstExprValue *const_val = &get_resolved_expr(size_node)->const_val; | 1754 | var_type->data.structure.is_unknown_size_array) |
| 1752 | if (!const_val->ok) { | 1755 | { |
| 1753 | TypeTableEntry *ptr_type = var_type->data.structure.fields[0].type_entry; | 1756 | assert(var_decl->type->type == NodeTypeArrayType); |
| 1754 | assert(ptr_type->id == TypeTableEntryIdPointer); | 1757 | AstNode *size_node = var_decl->type->data.array_type.size; |
| 1755 | TypeTableEntry *child_type = ptr_type->data.pointer.child_type; | 1758 | if (size_node) { |
| 1756 | | 1759 | ConstExprValue *const_val = &get_resolved_expr(size_node)->const_val; |
| 1757 | LLVMValueRef size_val = gen_expr(g, size_node); | 1760 | if (!const_val->ok) { |
| 1758 | | 1761 | TypeTableEntry *ptr_type = var_type->data.structure.fields[0].type_entry; |
| 1759 | add_debug_source_node(g, source_node); | 1762 | assert(ptr_type->id == TypeTableEntryIdPointer); |
| 1760 | LLVMValueRef ptr_val = LLVMBuildArrayAlloca(g->builder, child_type->type_ref, | 1763 | TypeTableEntry *child_type = ptr_type->data.pointer.child_type; |
| 1761 | size_val, ""); | 1764 | |
| 1762 | | 1765 | LLVMValueRef size_val = gen_expr(g, size_node); |
| 1763 | // store the freshly allocated pointer in the unknown size array struct | 1766 | |
| 1764 | LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, | 1767 | add_debug_source_node(g, source_node); |
| 1765 | variable->value_ref, 0, ""); | 1768 | LLVMValueRef ptr_val = LLVMBuildArrayAlloca(g->builder, child_type->type_ref, |
| 1766 | LLVMBuildStore(g->builder, ptr_val, ptr_field_ptr); | 1769 | size_val, ""); |
| 1767 | | 1770 | |
| 1768 | // store the size in the len field | 1771 | // store the freshly allocated pointer in the unknown size array struct |
| 1769 | LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, | 1772 | LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, |
| 1770 | variable->value_ref, 1, ""); | 1773 | variable->value_ref, 0, ""); |
| 1771 | LLVMBuildStore(g->builder, size_val, len_field_ptr); | 1774 | LLVMBuildStore(g->builder, ptr_val, ptr_field_ptr); |
| 1772 | | 1775 | |
| 1773 | // don't clobber what we just did with debug initialization | 1776 | // store the size in the len field |
| 1774 | ignore_uninit = true; | 1777 | LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, |
| 1775 | } | 1778 | variable->value_ref, 1, ""); |
| | 1779 | LLVMBuildStore(g->builder, size_val, len_field_ptr); |
| | 1780 | |
| | 1781 | // don't clobber what we just did with debug initialization |
| | 1782 | ignore_uninit = true; |
| 1776 | } | 1783 | } |
| 1777 | } | 1784 | } |
| 1778 | if (!ignore_uninit && g->build_type != CodeGenBuildTypeRelease) { | | |
| 1779 | // memset uninitialized memory to 0xa | | |
| 1780 | add_debug_source_node(g, source_node); | | |
| 1781 | LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0); | | |
| 1782 | LLVMValueRef fill_char = LLVMConstInt(LLVMInt8Type(), 0xaa, false); | | |
| 1783 | LLVMValueRef dest_ptr = LLVMBuildBitCast(g->builder, variable->value_ref, ptr_u8, ""); | | |
| 1784 | LLVMValueRef byte_count = LLVMConstInt(LLVMIntType(g->pointer_size_bytes * 8), | | |
| 1785 | variable->type->size_in_bits / 8, false); | | |
| 1786 | LLVMValueRef align_in_bytes = LLVMConstInt(LLVMInt32Type(), | | |
| 1787 | variable->type->align_in_bits / 8, false); | | |
| 1788 | LLVMValueRef params[] = { | | |
| 1789 | dest_ptr, | | |
| 1790 | fill_char, | | |
| 1791 | byte_count, | | |
| 1792 | align_in_bytes, | | |
| 1793 | LLVMConstNull(LLVMInt1Type()), // is volatile | | |
| 1794 | }; | | |
| 1795 | | | |
| 1796 | LLVMBuildCall(g->builder, g->memset_fn_val, params, 5, ""); | | |
| 1797 | } | | |
| 1798 | } | 1785 | } |
| | 1786 | if (!ignore_uninit && g->build_type != CodeGenBuildTypeRelease) { |
| | 1787 | // memset uninitialized memory to 0xa |
| | 1788 | add_debug_source_node(g, source_node); |
| | 1789 | LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0); |
| | 1790 | LLVMValueRef fill_char = LLVMConstInt(LLVMInt8Type(), 0xaa, false); |
| | 1791 | LLVMValueRef dest_ptr = LLVMBuildBitCast(g->builder, variable->value_ref, ptr_u8, ""); |
| | 1792 | LLVMValueRef byte_count = LLVMConstInt(LLVMIntType(g->pointer_size_bytes * 8), |
| | 1793 | variable->type->size_in_bits / 8, false); |
| | 1794 | LLVMValueRef align_in_bytes = LLVMConstInt(LLVMInt32Type(), |
| | 1795 | variable->type->align_in_bits / 8, false); |
| | 1796 | LLVMValueRef params[] = { |
| | 1797 | dest_ptr, |
| | 1798 | fill_char, |
| | 1799 | byte_count, |
| | 1800 | align_in_bytes, |
| | 1801 | LLVMConstNull(LLVMInt1Type()), // is volatile |
| | 1802 | }; |
| 1799 | | 1803 | |
| 1800 | LLVMZigDILocation *debug_loc = LLVMZigGetDebugLoc(source_node->line + 1, source_node->column + 1, | 1804 | LLVMBuildCall(g->builder, g->memset_fn_val, params, 5, ""); |
| 1801 | g->cur_block_context->di_scope); | 1805 | } |
| 1802 | LLVMZigInsertDeclareAtEnd(g->dbuilder, variable->value_ref, variable->di_loc_var, debug_loc, | | |
| 1803 | LLVMGetInsertBlock(g->builder)); | | |
| 1804 | return nullptr; | | |
| 1805 | } | 1806 | } |
| | 1807 | |
| | 1808 | LLVMZigDILocation *debug_loc = LLVMZigGetDebugLoc(source_node->line + 1, source_node->column + 1, |
| | 1809 | g->cur_block_context->di_scope); |
| | 1810 | LLVMZigInsertDeclareAtEnd(g->dbuilder, variable->value_ref, variable->di_loc_var, debug_loc, |
| | 1811 | LLVMGetInsertBlock(g->builder)); |
| | 1812 | return nullptr; |
| 1806 | } | 1813 | } |
| 1807 | | 1814 | |
| 1808 | static LLVMValueRef gen_var_decl_expr(CodeGen *g, AstNode *node) { | 1815 | static LLVMValueRef gen_var_decl_expr(CodeGen *g, AstNode *node) { |
| ... | @@ -2035,6 +2042,10 @@ static void build_label_blocks(CodeGen *g, AstNode *block_node) { | ... | @@ -2035,6 +2042,10 @@ static void build_label_blocks(CodeGen *g, AstNode *block_node) { |
| 2035 | static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val) { | 2042 | static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val) { |
| 2036 | assert(const_val->ok); | 2043 | assert(const_val->ok); |
| 2037 | | 2044 | |
| | 2045 | if (const_val->undef) { |
| | 2046 | return LLVMConstNull(type_entry->type_ref); |
| | 2047 | } |
| | 2048 | |
| 2038 | if (type_entry->id == TypeTableEntryIdInt) { | 2049 | if (type_entry->id == TypeTableEntryIdInt) { |
| 2039 | return LLVMConstInt(type_entry->type_ref, bignum_to_twos_complement(&const_val->data.x_bignum), false); | 2050 | return LLVMConstInt(type_entry->type_ref, bignum_to_twos_complement(&const_val->data.x_bignum), false); |
| 2040 | } else if (type_entry->id == TypeTableEntryIdFloat) { | 2051 | } else if (type_entry->id == TypeTableEntryIdFloat) { |
| ... | @@ -2389,6 +2400,11 @@ static void define_builtin_types(CodeGen *g) { | ... | @@ -2389,6 +2400,11 @@ static void define_builtin_types(CodeGen *g) { |
| 2389 | buf_init_from_str(&entry->name, "(integer literal)"); | 2400 | buf_init_from_str(&entry->name, "(integer literal)"); |
| 2390 | g->builtin_types.entry_num_lit_int = entry; | 2401 | g->builtin_types.entry_num_lit_int = entry; |
| 2391 | } | 2402 | } |
| | 2403 | { |
| | 2404 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdUndefLit); |
| | 2405 | buf_init_from_str(&entry->name, "(undefined)"); |
| | 2406 | g->builtin_types.entry_undef = entry; |
| | 2407 | } |
| 2392 | | 2408 | |
| 2393 | for (int i = 0; i < array_length(int_sizes_in_bits); i += 1) { | 2409 | for (int i = 0; i < array_length(int_sizes_in_bits); i += 1) { |
| 2394 | int size_in_bits = int_sizes_in_bits[i]; | 2410 | int size_in_bits = int_sizes_in_bits[i]; |