| ... | ... | @@ -1725,84 +1725,91 @@ static LLVMValueRef gen_var_decl_raw(CodeGen *g, AstNode *source_node, AstNodeVa |
| 1725 | 1725 | } |
| 1726 | 1726 | if (variable->type->size_in_bits == 0) { |
| 1727 | 1727 | return nullptr; |
| 1728 | | } else { |
| 1729 | | if (var_decl->expr) { |
| 1730 | | TypeTableEntry *expr_type = get_expr_type(var_decl->expr); |
| 1731 | | LLVMValueRef value; |
| 1732 | | if (unwrap_maybe) { |
| 1733 | | assert(var_decl->expr); |
| 1734 | | assert(expr_type->id == TypeTableEntryIdMaybe); |
| 1735 | | value = gen_unwrap_maybe(g, source_node, *init_value); |
| 1736 | | expr_type = expr_type->data.maybe.child_type; |
| 1737 | | } else { |
| 1738 | | value = *init_value; |
| 1739 | | } |
| 1740 | | gen_assign_raw(g, var_decl->expr, BinOpTypeAssign, variable->value_ref, |
| 1741 | | value, variable->type, expr_type); |
| 1728 | } |
| 1729 | |
| 1730 | bool have_init_expr = false; |
| 1731 | if (var_decl->expr) { |
| 1732 | ConstExprValue *const_val = &get_resolved_expr(var_decl->expr)->const_val; |
| 1733 | if (!const_val->ok || !const_val->undef) { |
| 1734 | have_init_expr = true; |
| 1735 | } |
| 1736 | } |
| 1737 | if (have_init_expr) { |
| 1738 | TypeTableEntry *expr_type = get_expr_type(var_decl->expr); |
| 1739 | LLVMValueRef value; |
| 1740 | if (unwrap_maybe) { |
| 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 | 1745 | } else { |
| 1743 | | bool ignore_uninit = false; |
| 1744 | | TypeTableEntry *var_type = get_type_for_type_node(var_decl->type); |
| 1745 | | if (var_type->id == TypeTableEntryIdStruct && |
| 1746 | | var_type->data.structure.is_unknown_size_array) |
| 1747 | | { |
| 1748 | | assert(var_decl->type->type == NodeTypeArrayType); |
| 1749 | | AstNode *size_node = var_decl->type->data.array_type.size; |
| 1750 | | if (size_node) { |
| 1751 | | ConstExprValue *const_val = &get_resolved_expr(size_node)->const_val; |
| 1752 | | if (!const_val->ok) { |
| 1753 | | TypeTableEntry *ptr_type = var_type->data.structure.fields[0].type_entry; |
| 1754 | | assert(ptr_type->id == TypeTableEntryIdPointer); |
| 1755 | | TypeTableEntry *child_type = ptr_type->data.pointer.child_type; |
| 1756 | | |
| 1757 | | LLVMValueRef size_val = gen_expr(g, size_node); |
| 1758 | | |
| 1759 | | add_debug_source_node(g, source_node); |
| 1760 | | LLVMValueRef ptr_val = LLVMBuildArrayAlloca(g->builder, child_type->type_ref, |
| 1761 | | size_val, ""); |
| 1762 | | |
| 1763 | | // store the freshly allocated pointer in the unknown size array struct |
| 1764 | | LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, |
| 1765 | | variable->value_ref, 0, ""); |
| 1766 | | LLVMBuildStore(g->builder, ptr_val, ptr_field_ptr); |
| 1767 | | |
| 1768 | | // store the size in the len field |
| 1769 | | LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, |
| 1770 | | variable->value_ref, 1, ""); |
| 1771 | | LLVMBuildStore(g->builder, size_val, len_field_ptr); |
| 1772 | | |
| 1773 | | // don't clobber what we just did with debug initialization |
| 1774 | | ignore_uninit = true; |
| 1775 | | } |
| 1746 | value = *init_value; |
| 1747 | } |
| 1748 | gen_assign_raw(g, var_decl->expr, BinOpTypeAssign, variable->value_ref, |
| 1749 | value, variable->type, expr_type); |
| 1750 | } else { |
| 1751 | bool ignore_uninit = false; |
| 1752 | TypeTableEntry *var_type = get_type_for_type_node(var_decl->type); |
| 1753 | if (var_type->id == TypeTableEntryIdStruct && |
| 1754 | var_type->data.structure.is_unknown_size_array) |
| 1755 | { |
| 1756 | assert(var_decl->type->type == NodeTypeArrayType); |
| 1757 | AstNode *size_node = var_decl->type->data.array_type.size; |
| 1758 | if (size_node) { |
| 1759 | ConstExprValue *const_val = &get_resolved_expr(size_node)->const_val; |
| 1760 | if (!const_val->ok) { |
| 1761 | TypeTableEntry *ptr_type = var_type->data.structure.fields[0].type_entry; |
| 1762 | assert(ptr_type->id == TypeTableEntryIdPointer); |
| 1763 | TypeTableEntry *child_type = ptr_type->data.pointer.child_type; |
| 1764 | |
| 1765 | LLVMValueRef size_val = gen_expr(g, size_node); |
| 1766 | |
| 1767 | add_debug_source_node(g, source_node); |
| 1768 | LLVMValueRef ptr_val = LLVMBuildArrayAlloca(g->builder, child_type->type_ref, |
| 1769 | size_val, ""); |
| 1770 | |
| 1771 | // store the freshly allocated pointer in the unknown size array struct |
| 1772 | LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, |
| 1773 | variable->value_ref, 0, ""); |
| 1774 | LLVMBuildStore(g->builder, ptr_val, ptr_field_ptr); |
| 1775 | |
| 1776 | // store the size in the len field |
| 1777 | LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, |
| 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, |
| 1801 | | g->cur_block_context->di_scope); |
| 1802 | | LLVMZigInsertDeclareAtEnd(g->dbuilder, variable->value_ref, variable->di_loc_var, debug_loc, |
| 1803 | | LLVMGetInsertBlock(g->builder)); |
| 1804 | | return nullptr; |
| 1804 | LLVMBuildCall(g->builder, g->memset_fn_val, params, 5, ""); |
| 1805 | } |
| 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 | 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 | 2042 | static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val) { |
| 2036 | 2043 | assert(const_val->ok); |
| 2037 | 2044 | |
| 2045 | if (const_val->undef) { |
| 2046 | return LLVMConstNull(type_entry->type_ref); |
| 2047 | } |
| 2048 | |
| 2038 | 2049 | if (type_entry->id == TypeTableEntryIdInt) { |
| 2039 | 2050 | return LLVMConstInt(type_entry->type_ref, bignum_to_twos_complement(&const_val->data.x_bignum), false); |
| 2040 | 2051 | } else if (type_entry->id == TypeTableEntryIdFloat) { |
| ... | ... | @@ -2389,6 +2400,11 @@ static void define_builtin_types(CodeGen *g) { |
| 2389 | 2400 | buf_init_from_str(&entry->name, "(integer literal)"); |
| 2390 | 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 | 2409 | for (int i = 0; i < array_length(int_sizes_in_bits); i += 1) { |
| 2394 | 2410 | int size_in_bits = int_sizes_in_bits[i]; |