| ... | @@ -1755,12 +1755,16 @@ static LLVMValueRef ir_render_asm(CodeGen *g, IrExecutable *executable, IrInstru | ... | @@ -1755,12 +1755,16 @@ static LLVMValueRef ir_render_asm(CodeGen *g, IrExecutable *executable, IrInstru |
| 1755 | static LLVMValueRef gen_non_null_bit(CodeGen *g, TypeTableEntry *maybe_type, LLVMValueRef maybe_handle) { | 1755 | static LLVMValueRef gen_non_null_bit(CodeGen *g, TypeTableEntry *maybe_type, LLVMValueRef maybe_handle) { |
| 1756 | assert(maybe_type->id == TypeTableEntryIdMaybe); | 1756 | assert(maybe_type->id == TypeTableEntryIdMaybe); |
| 1757 | TypeTableEntry *child_type = maybe_type->data.maybe.child_type; | 1757 | TypeTableEntry *child_type = maybe_type->data.maybe.child_type; |
| 1758 | bool maybe_is_ptr = (child_type->id == TypeTableEntryIdPointer || child_type->id == TypeTableEntryIdFn); | 1758 | if (child_type->zero_bits) { |
| 1759 | if (maybe_is_ptr) { | 1759 | return maybe_handle; |
| 1760 | return LLVMBuildICmp(g->builder, LLVMIntNE, maybe_handle, LLVMConstNull(maybe_type->type_ref), ""); | | |
| 1761 | } else { | 1760 | } else { |
| 1762 | LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP(g->builder, maybe_handle, maybe_null_index, ""); | 1761 | bool maybe_is_ptr = (child_type->id == TypeTableEntryIdPointer || child_type->id == TypeTableEntryIdFn); |
| 1763 | return LLVMBuildLoad(g->builder, maybe_field_ptr, ""); | 1762 | if (maybe_is_ptr) { |
| | 1763 | return LLVMBuildICmp(g->builder, LLVMIntNE, maybe_handle, LLVMConstNull(maybe_type->type_ref), ""); |
| | 1764 | } else { |
| | 1765 | LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP(g->builder, maybe_handle, maybe_null_index, ""); |
| | 1766 | return LLVMBuildLoad(g->builder, maybe_field_ptr, ""); |
| | 1767 | } |
| 1764 | } | 1768 | } |
| 1765 | } | 1769 | } |
| 1766 | | 1770 | |
| ... | @@ -1779,7 +1783,6 @@ static LLVMValueRef ir_render_unwrap_maybe(CodeGen *g, IrExecutable *executable, | ... | @@ -1779,7 +1783,6 @@ static LLVMValueRef ir_render_unwrap_maybe(CodeGen *g, IrExecutable *executable, |
| 1779 | TypeTableEntry *maybe_type = ptr_type->data.pointer.child_type; | 1783 | TypeTableEntry *maybe_type = ptr_type->data.pointer.child_type; |
| 1780 | assert(maybe_type->id == TypeTableEntryIdMaybe); | 1784 | assert(maybe_type->id == TypeTableEntryIdMaybe); |
| 1781 | TypeTableEntry *child_type = maybe_type->data.maybe.child_type; | 1785 | TypeTableEntry *child_type = maybe_type->data.maybe.child_type; |
| 1782 | bool maybe_is_ptr = (child_type->id == TypeTableEntryIdPointer || child_type->id == TypeTableEntryIdFn); | | |
| 1783 | LLVMValueRef maybe_ptr = ir_llvm_value(g, instruction->value); | 1786 | LLVMValueRef maybe_ptr = ir_llvm_value(g, instruction->value); |
| 1784 | LLVMValueRef maybe_handle = get_handle_value(g, maybe_ptr, maybe_type, is_volatile); | 1787 | LLVMValueRef maybe_handle = get_handle_value(g, maybe_ptr, maybe_type, is_volatile); |
| 1785 | if (ir_want_debug_safety(g, &instruction->base) && instruction->safety_check_on) { | 1788 | if (ir_want_debug_safety(g, &instruction->base) && instruction->safety_check_on) { |
| ... | @@ -1793,11 +1796,16 @@ static LLVMValueRef ir_render_unwrap_maybe(CodeGen *g, IrExecutable *executable, | ... | @@ -1793,11 +1796,16 @@ static LLVMValueRef ir_render_unwrap_maybe(CodeGen *g, IrExecutable *executable, |
| 1793 | | 1796 | |
| 1794 | LLVMPositionBuilderAtEnd(g->builder, ok_block); | 1797 | LLVMPositionBuilderAtEnd(g->builder, ok_block); |
| 1795 | } | 1798 | } |
| 1796 | if (maybe_is_ptr) { | 1799 | if (child_type->zero_bits) { |
| 1797 | return maybe_ptr; | 1800 | return nullptr; |
| 1798 | } else { | 1801 | } else { |
| 1799 | LLVMValueRef maybe_struct_ref = get_handle_value(g, maybe_ptr, maybe_type, is_volatile); | 1802 | bool maybe_is_ptr = (child_type->id == TypeTableEntryIdPointer || child_type->id == TypeTableEntryIdFn); |
| 1800 | return LLVMBuildStructGEP(g->builder, maybe_struct_ref, maybe_child_index, ""); | 1803 | if (maybe_is_ptr) { |
| | 1804 | return maybe_ptr; |
| | 1805 | } else { |
| | 1806 | LLVMValueRef maybe_struct_ref = get_handle_value(g, maybe_ptr, maybe_type, is_volatile); |
| | 1807 | return LLVMBuildStructGEP(g->builder, maybe_struct_ref, maybe_child_index, ""); |
| | 1808 | } |
| 1801 | } | 1809 | } |
| 1802 | } | 1810 | } |
| 1803 | | 1811 | |
| ... | @@ -2319,6 +2327,10 @@ static LLVMValueRef ir_render_maybe_wrap(CodeGen *g, IrExecutable *executable, I | ... | @@ -2319,6 +2327,10 @@ static LLVMValueRef ir_render_maybe_wrap(CodeGen *g, IrExecutable *executable, I |
| 2319 | | 2327 | |
| 2320 | TypeTableEntry *child_type = wanted_type->data.maybe.child_type; | 2328 | TypeTableEntry *child_type = wanted_type->data.maybe.child_type; |
| 2321 | | 2329 | |
| | 2330 | if (child_type->zero_bits) { |
| | 2331 | return LLVMConstInt(LLVMInt1Type(), 1, false); |
| | 2332 | } |
| | 2333 | |
| 2322 | LLVMValueRef payload_val = ir_llvm_value(g, instruction->value); | 2334 | LLVMValueRef payload_val = ir_llvm_value(g, instruction->value); |
| 2323 | if (child_type->id == TypeTableEntryIdPointer || | 2335 | if (child_type->id == TypeTableEntryIdPointer || |
| 2324 | child_type->id == TypeTableEntryIdFn) | 2336 | child_type->id == TypeTableEntryIdFn) |
| ... | @@ -2806,7 +2818,9 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) { | ... | @@ -2806,7 +2818,9 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) { |
| 2806 | case TypeTableEntryIdMaybe: | 2818 | case TypeTableEntryIdMaybe: |
| 2807 | { | 2819 | { |
| 2808 | TypeTableEntry *child_type = canon_type->data.maybe.child_type; | 2820 | TypeTableEntry *child_type = canon_type->data.maybe.child_type; |
| 2809 | if (child_type->id == TypeTableEntryIdPointer || | 2821 | if (child_type->zero_bits) { |
| | 2822 | return LLVMConstInt(LLVMInt1Type(), const_val->data.x_maybe ? 1 : 0, false); |
| | 2823 | } else if (child_type->id == TypeTableEntryIdPointer || |
| 2810 | child_type->id == TypeTableEntryIdFn) | 2824 | child_type->id == TypeTableEntryIdFn) |
| 2811 | { | 2825 | { |
| 2812 | if (const_val->data.x_maybe) { | 2826 | if (const_val->data.x_maybe) { |
| ... | @@ -4322,7 +4336,10 @@ static void get_c_type(CodeGen *g, TypeTableEntry *type_entry, Buf *out_buf) { | ... | @@ -4322,7 +4336,10 @@ static void get_c_type(CodeGen *g, TypeTableEntry *type_entry, Buf *out_buf) { |
| 4322 | case TypeTableEntryIdMaybe: | 4336 | case TypeTableEntryIdMaybe: |
| 4323 | { | 4337 | { |
| 4324 | TypeTableEntry *child_type = type_entry->data.maybe.child_type; | 4338 | TypeTableEntry *child_type = type_entry->data.maybe.child_type; |
| 4325 | if (child_type->id == TypeTableEntryIdPointer || | 4339 | if (child_type->zero_bits) { |
| | 4340 | buf_init_from_str(out_buf, "bool"); |
| | 4341 | return; |
| | 4342 | } else if (child_type->id == TypeTableEntryIdPointer || |
| 4326 | child_type->id == TypeTableEntryIdFn) | 4343 | child_type->id == TypeTableEntryIdFn) |
| 4327 | { | 4344 | { |
| 4328 | return get_c_type(g, child_type, out_buf); | 4345 | return get_c_type(g, child_type, out_buf); |