| author | |
| committer | |
| log | 7f7823e23cfd82739401f43a329106bee0748b10 |
| tree | eb8382e8e704f72f33494a20879d303b53d5db04 |
| parent | d6e84e325bab360c6b6980dc2d57df872b9affdc |
closes #7775 files changed, 76 insertions(+), 22 deletions(-)
src/all_types.hpp+5-5| ... | ... | @@ -144,6 +144,8 @@ enum ConstPtrSpecial { |
| 144 | 144 | // This means that the pointer represents memory of assigning to _. |
| 145 | 145 | // That is, storing discards the data, and loading is invalid. |
| 146 | 146 | ConstPtrSpecialDiscard, |
| 147 | // This is actually a function. | |
| 148 | ConstPtrSpecialFunction, | |
| 147 | 149 | }; |
| 148 | 150 | |
| 149 | 151 | enum ConstPtrMut { |
| ... | ... | @@ -180,6 +182,9 @@ struct ConstPtrValue { |
| 180 | 182 | struct { |
| 181 | 183 | uint64_t addr; |
| 182 | 184 | } hard_coded_addr; |
| 185 | struct { | |
| 186 | FnTableEntry *fn_entry; | |
| 187 | } fn; | |
| 183 | 188 | } data; |
| 184 | 189 | }; |
| 185 | 190 | |
| ... | ... | @@ -222,10 +227,6 @@ enum RuntimeHintPtr { |
| 222 | 227 | RuntimeHintPtrNonStack, |
| 223 | 228 | }; |
| 224 | 229 | |
| 225 | struct ConstFn { | |
| 226 | FnTableEntry *fn_entry; | |
| 227 | }; | |
| 228 | ||
| 229 | 230 | struct ConstGlobalRefs { |
| 230 | 231 | LLVMValueRef llvm_value; |
| 231 | 232 | LLVMValueRef llvm_global; |
| ... | ... | @@ -244,7 +245,6 @@ struct ConstExprValue { |
| 244 | 245 | double x_f64; |
| 245 | 246 | float128_t x_f128; |
| 246 | 247 | bool x_bool; |
| 247 | ConstFn x_fn; | |
| 248 | 248 | ConstBoundFnValue x_bound_fn; |
| 249 | 249 | TypeTableEntry *x_type; |
| 250 | 250 | ConstExprValue *x_maybe; |
src/analyze.cpp+25-10| ... | ... | @@ -4447,6 +4447,10 @@ static uint32_t hash_const_val(ConstExprValue *const_val) { |
| 4447 | 4447 | case TypeTableEntryIdArgTuple: |
| 4448 | 4448 | return (uint32_t)const_val->data.x_arg_tuple.start_index * (uint32_t)281907309 + |
| 4449 | 4449 | (uint32_t)const_val->data.x_arg_tuple.end_index * (uint32_t)2290442768; |
| 4450 | case TypeTableEntryIdFn: | |
| 4451 | assert(const_val->data.x_ptr.mut == ConstPtrMutComptimeConst); | |
| 4452 | assert(const_val->data.x_ptr.special == ConstPtrSpecialFunction); | |
| 4453 | return 3677364617 ^ hash_ptr(const_val->data.x_ptr.data.fn.fn_entry); | |
| 4450 | 4454 | case TypeTableEntryIdPointer: |
| 4451 | 4455 | { |
| 4452 | 4456 | uint32_t hash_val = 0; |
| ... | ... | @@ -4486,6 +4490,10 @@ static uint32_t hash_const_val(ConstExprValue *const_val) { |
| 4486 | 4490 | case ConstPtrSpecialDiscard: |
| 4487 | 4491 | hash_val += 2010123162; |
| 4488 | 4492 | return hash_val; |
| 4493 | case ConstPtrSpecialFunction: | |
| 4494 | hash_val += (uint32_t)2590901619; | |
| 4495 | hash_val += hash_ptr(const_val->data.x_ptr.data.fn.fn_entry); | |
| 4496 | return hash_val; | |
| 4489 | 4497 | } |
| 4490 | 4498 | zig_unreachable(); |
| 4491 | 4499 | } |
| ... | ... | @@ -4517,8 +4525,6 @@ static uint32_t hash_const_val(ConstExprValue *const_val) { |
| 4517 | 4525 | case TypeTableEntryIdErrorSet: |
| 4518 | 4526 | assert(const_val->data.x_err_set != nullptr); |
| 4519 | 4527 | return const_val->data.x_err_set->value ^ 2630160122; |
| 4520 | case TypeTableEntryIdFn: | |
| 4521 | return 4133894920 ^ hash_ptr(const_val->data.x_fn.fn_entry); | |
| 4522 | 4528 | case TypeTableEntryIdNamespace: |
| 4523 | 4529 | return hash_ptr(const_val->data.x_import); |
| 4524 | 4530 | case TypeTableEntryIdBlock: |
| ... | ... | @@ -5150,8 +5156,6 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) { |
| 5150 | 5156 | return true; |
| 5151 | 5157 | case TypeTableEntryIdErrorSet: |
| 5152 | 5158 | return a->data.x_err_set->value == b->data.x_err_set->value; |
| 5153 | case TypeTableEntryIdFn: | |
| 5154 | return a->data.x_fn.fn_entry == b->data.x_fn.fn_entry; | |
| 5155 | 5159 | case TypeTableEntryIdBool: |
| 5156 | 5160 | return a->data.x_bool == b->data.x_bool; |
| 5157 | 5161 | case TypeTableEntryIdFloat: |
| ... | ... | @@ -5172,6 +5176,7 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) { |
| 5172 | 5176 | case TypeTableEntryIdNumLitInt: |
| 5173 | 5177 | return bigint_cmp(&a->data.x_bigint, &b->data.x_bigint) == CmpEQ; |
| 5174 | 5178 | case TypeTableEntryIdPointer: |
| 5179 | case TypeTableEntryIdFn: | |
| 5175 | 5180 | if (a->data.x_ptr.special != b->data.x_ptr.special) |
| 5176 | 5181 | return false; |
| 5177 | 5182 | if (a->data.x_ptr.mut != b->data.x_ptr.mut) |
| ... | ... | @@ -5211,6 +5216,8 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) { |
| 5211 | 5216 | return true; |
| 5212 | 5217 | case ConstPtrSpecialDiscard: |
| 5213 | 5218 | return true; |
| 5219 | case ConstPtrSpecialFunction: | |
| 5220 | return a->data.x_ptr.data.fn.fn_entry == b->data.x_ptr.data.fn.fn_entry; | |
| 5214 | 5221 | } |
| 5215 | 5222 | zig_unreachable(); |
| 5216 | 5223 | case TypeTableEntryIdArray: |
| ... | ... | @@ -5371,6 +5378,14 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { |
| 5371 | 5378 | buf_appendf(buf, "%s", value); |
| 5372 | 5379 | return; |
| 5373 | 5380 | } |
| 5381 | case TypeTableEntryIdFn: | |
| 5382 | { | |
| 5383 | assert(const_val->data.x_ptr.mut == ConstPtrMutComptimeConst); | |
| 5384 | assert(const_val->data.x_ptr.special == ConstPtrSpecialFunction); | |
| 5385 | FnTableEntry *fn_entry = const_val->data.x_ptr.data.fn.fn_entry; | |
| 5386 | buf_appendf(buf, "%s", buf_ptr(&fn_entry->symbol_name)); | |
| 5387 | return; | |
| 5388 | } | |
| 5374 | 5389 | case TypeTableEntryIdPointer: |
| 5375 | 5390 | switch (const_val->data.x_ptr.special) { |
| 5376 | 5391 | case ConstPtrSpecialInvalid: |
| ... | ... | @@ -5396,14 +5411,14 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { |
| 5396 | 5411 | case ConstPtrSpecialDiscard: |
| 5397 | 5412 | buf_append_str(buf, "&_"); |
| 5398 | 5413 | return; |
| 5414 | case ConstPtrSpecialFunction: | |
| 5415 | { | |
| 5416 | FnTableEntry *fn_entry = const_val->data.x_ptr.data.fn.fn_entry; | |
| 5417 | buf_appendf(buf, "@ptrCast(%s, %s)", buf_ptr(&const_val->type->name), buf_ptr(&fn_entry->symbol_name)); | |
| 5418 | return; | |
| 5419 | } | |
| 5399 | 5420 | } |
| 5400 | 5421 | zig_unreachable(); |
| 5401 | case TypeTableEntryIdFn: | |
| 5402 | { | |
| 5403 | FnTableEntry *fn_entry = const_val->data.x_fn.fn_entry; | |
| 5404 | buf_appendf(buf, "%s", buf_ptr(&fn_entry->symbol_name)); | |
| 5405 | return; | |
| 5406 | } | |
| 5407 | 5422 | case TypeTableEntryIdBlock: |
| 5408 | 5423 | { |
| 5409 | 5424 | AstNode *node = const_val->data.x_block->source_node; |
src/codegen.cpp+8-2| ... | ... | @@ -4840,7 +4840,9 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c |
| 4840 | 4840 | case TypeTableEntryIdEnum: |
| 4841 | 4841 | return bigint_to_llvm_const(type_entry->type_ref, &const_val->data.x_enum_tag); |
| 4842 | 4842 | case TypeTableEntryIdFn: |
| 4843 | return fn_llvm_value(g, const_val->data.x_fn.fn_entry); | |
| 4843 | assert(const_val->data.x_ptr.special == ConstPtrSpecialFunction); | |
| 4844 | assert(const_val->data.x_ptr.mut == ConstPtrMutComptimeConst); | |
| 4845 | return fn_llvm_value(g, const_val->data.x_ptr.data.fn.fn_entry); | |
| 4844 | 4846 | case TypeTableEntryIdPointer: |
| 4845 | 4847 | { |
| 4846 | 4848 | render_const_val_global(g, const_val, name); |
| ... | ... | @@ -4909,6 +4911,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c |
| 4909 | 4911 | render_const_val_global(g, const_val, ""); |
| 4910 | 4912 | return const_val->global_refs->llvm_value; |
| 4911 | 4913 | } |
| 4914 | case ConstPtrSpecialFunction: | |
| 4915 | return LLVMConstBitCast(fn_llvm_value(g, const_val->data.x_ptr.data.fn.fn_entry), const_val->type->type_ref); | |
| 4912 | 4916 | } |
| 4913 | 4917 | } |
| 4914 | 4918 | zig_unreachable(); |
| ... | ... | @@ -6313,7 +6317,9 @@ static void create_test_compile_var_and_add_test_runner(CodeGen *g) { |
| 6313 | 6317 | ConstExprValue *fn_field = &this_val->data.x_struct.fields[1]; |
| 6314 | 6318 | fn_field->type = fn_type; |
| 6315 | 6319 | fn_field->special = ConstValSpecialStatic; |
| 6316 | fn_field->data.x_fn.fn_entry = test_fn_entry; | |
| 6320 | fn_field->data.x_ptr.special = ConstPtrSpecialFunction; | |
| 6321 | fn_field->data.x_ptr.mut = ConstPtrMutComptimeConst; | |
| 6322 | fn_field->data.x_ptr.data.fn.fn_entry = test_fn_entry; | |
| 6317 | 6323 | } |
| 6318 | 6324 | |
| 6319 | 6325 | ConstExprValue *test_fn_slice = create_const_slice(g, test_fn_array, 0, g->test_fns.length, true); |
src/ir.cpp+31-5| ... | ... | @@ -130,6 +130,8 @@ ConstExprValue *const_ptr_pointee(CodeGen *g, ConstExprValue *const_val) { |
| 130 | 130 | zig_unreachable(); |
| 131 | 131 | case ConstPtrSpecialDiscard: |
| 132 | 132 | zig_unreachable(); |
| 133 | case ConstPtrSpecialFunction: | |
| 134 | zig_unreachable(); | |
| 133 | 135 | } |
| 134 | 136 | zig_unreachable(); |
| 135 | 137 | } |
| ... | ... | @@ -875,7 +877,9 @@ static IrInstruction *ir_create_const_fn(IrBuilder *irb, Scope *scope, AstNode * |
| 875 | 877 | IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(irb, scope, source_node); |
| 876 | 878 | const_instruction->base.value.type = fn_entry->type_entry; |
| 877 | 879 | const_instruction->base.value.special = ConstValSpecialStatic; |
| 878 | const_instruction->base.value.data.x_fn.fn_entry = fn_entry; | |
| 880 | const_instruction->base.value.data.x_ptr.data.fn.fn_entry = fn_entry; | |
| 881 | const_instruction->base.value.data.x_ptr.mut = ConstPtrMutComptimeConst; | |
| 882 | const_instruction->base.value.data.x_ptr.special = ConstPtrSpecialFunction; | |
| 879 | 883 | return &const_instruction->base; |
| 880 | 884 | } |
| 881 | 885 | |
| ... | ... | @@ -8723,7 +8727,8 @@ static FnTableEntry *ir_resolve_fn(IrAnalyze *ira, IrInstruction *fn_value) { |
| 8723 | 8727 | if (!const_val) |
| 8724 | 8728 | return nullptr; |
| 8725 | 8729 | |
| 8726 | return const_val->data.x_fn.fn_entry; | |
| 8730 | assert(const_val->data.x_ptr.special == ConstPtrSpecialFunction); | |
| 8731 | return const_val->data.x_ptr.data.fn.fn_entry; | |
| 8727 | 8732 | } |
| 8728 | 8733 | |
| 8729 | 8734 | static IrInstruction *ir_analyze_maybe_wrap(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, TypeTableEntry *wanted_type) { |
| ... | ... | @@ -11311,7 +11316,8 @@ static TypeTableEntry *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructi |
| 11311 | 11316 | case TypeTableEntryIdUnreachable: |
| 11312 | 11317 | zig_unreachable(); |
| 11313 | 11318 | case TypeTableEntryIdFn: { |
| 11314 | FnTableEntry *fn_entry = target->value.data.x_fn.fn_entry; | |
| 11319 | assert(target->value.data.x_ptr.special == ConstPtrSpecialFunction); | |
| 11320 | FnTableEntry *fn_entry = target->value.data.x_ptr.data.fn.fn_entry; | |
| 11315 | 11321 | CallingConvention cc = fn_entry->type_entry->data.fn.fn_type_id.cc; |
| 11316 | 11322 | switch (cc) { |
| 11317 | 11323 | case CallingConventionUnspecified: { |
| ... | ... | @@ -12852,6 +12858,8 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc |
| 12852 | 12858 | zig_panic("TODO elem ptr on a const inner struct"); |
| 12853 | 12859 | case ConstPtrSpecialHardCodedAddr: |
| 12854 | 12860 | zig_unreachable(); |
| 12861 | case ConstPtrSpecialFunction: | |
| 12862 | zig_panic("TODO element ptr of a function casted to a ptr"); | |
| 12855 | 12863 | } |
| 12856 | 12864 | if (new_index >= mem_size) { |
| 12857 | 12865 | ir_add_error_node(ira, elem_ptr_instruction->base.source_node, |
| ... | ... | @@ -12901,6 +12909,8 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc |
| 12901 | 12909 | zig_panic("TODO elem ptr on a slice backed by const inner struct"); |
| 12902 | 12910 | case ConstPtrSpecialHardCodedAddr: |
| 12903 | 12911 | zig_unreachable(); |
| 12912 | case ConstPtrSpecialFunction: | |
| 12913 | zig_panic("TODO elem ptr on a slice that was ptrcast from a function"); | |
| 12904 | 12914 | } |
| 12905 | 12915 | return return_type; |
| 12906 | 12916 | } else if (array_type->id == TypeTableEntryIdArray) { |
| ... | ... | @@ -13101,7 +13111,9 @@ static TypeTableEntry *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source |
| 13101 | 13111 | ConstExprValue *const_val = create_const_vals(1); |
| 13102 | 13112 | const_val->special = ConstValSpecialStatic; |
| 13103 | 13113 | const_val->type = fn_entry->type_entry; |
| 13104 | const_val->data.x_fn.fn_entry = fn_entry; | |
| 13114 | const_val->data.x_ptr.data.fn.fn_entry = fn_entry; | |
| 13115 | const_val->data.x_ptr.special = ConstPtrSpecialFunction; | |
| 13116 | const_val->data.x_ptr.mut = ConstPtrMutComptimeConst; | |
| 13105 | 13117 | |
| 13106 | 13118 | if (tld_fn->extern_lib_name != nullptr) { |
| 13107 | 13119 | add_link_lib_symbol(ira, tld_fn->extern_lib_name, &fn_entry->symbol_name, source_instruction->source_node); |
| ... | ... | @@ -13771,7 +13783,8 @@ static TypeTableEntry *ir_analyze_instruction_set_float_mode(IrAnalyze *ira, |
| 13771 | 13783 | fast_math_off_ptr = &block_scope->fast_math_off; |
| 13772 | 13784 | fast_math_set_node_ptr = &block_scope->fast_math_set_node; |
| 13773 | 13785 | } else if (target_type->id == TypeTableEntryIdFn) { |
| 13774 | FnTableEntry *target_fn = target_val->data.x_fn.fn_entry; | |
| 13786 | assert(target_val->data.x_ptr.special == ConstPtrSpecialFunction); | |
| 13787 | FnTableEntry *target_fn = target_val->data.x_ptr.data.fn.fn_entry; | |
| 13775 | 13788 | assert(target_fn->def_scope); |
| 13776 | 13789 | fast_math_off_ptr = &target_fn->def_scope->fast_math_off; |
| 13777 | 13790 | fast_math_set_node_ptr = &target_fn->def_scope->fast_math_set_node; |
| ... | ... | @@ -15673,6 +15686,8 @@ static TypeTableEntry *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructi |
| 15673 | 15686 | zig_panic("TODO memset on const inner struct"); |
| 15674 | 15687 | case ConstPtrSpecialHardCodedAddr: |
| 15675 | 15688 | zig_unreachable(); |
| 15689 | case ConstPtrSpecialFunction: | |
| 15690 | zig_panic("TODO memset on ptr cast from function"); | |
| 15676 | 15691 | } |
| 15677 | 15692 | |
| 15678 | 15693 | size_t count = bigint_as_unsigned(&casted_count->value.data.x_bigint); |
| ... | ... | @@ -15769,6 +15784,8 @@ static TypeTableEntry *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructi |
| 15769 | 15784 | zig_panic("TODO memcpy on const inner struct"); |
| 15770 | 15785 | case ConstPtrSpecialHardCodedAddr: |
| 15771 | 15786 | zig_unreachable(); |
| 15787 | case ConstPtrSpecialFunction: | |
| 15788 | zig_panic("TODO memcpy on ptr cast from function"); | |
| 15772 | 15789 | } |
| 15773 | 15790 | |
| 15774 | 15791 | if (dest_start + count > dest_end) { |
| ... | ... | @@ -15803,6 +15820,8 @@ static TypeTableEntry *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructi |
| 15803 | 15820 | zig_panic("TODO memcpy on const inner struct"); |
| 15804 | 15821 | case ConstPtrSpecialHardCodedAddr: |
| 15805 | 15822 | zig_unreachable(); |
| 15823 | case ConstPtrSpecialFunction: | |
| 15824 | zig_panic("TODO memcpy on ptr cast from function"); | |
| 15806 | 15825 | } |
| 15807 | 15826 | |
| 15808 | 15827 | if (src_start + count > src_end) { |
| ... | ... | @@ -15925,6 +15944,8 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio |
| 15925 | 15944 | abs_offset = 0; |
| 15926 | 15945 | rel_end = SIZE_MAX; |
| 15927 | 15946 | break; |
| 15947 | case ConstPtrSpecialFunction: | |
| 15948 | zig_panic("TODO slice of ptr cast from function"); | |
| 15928 | 15949 | } |
| 15929 | 15950 | } else if (is_slice(array_type)) { |
| 15930 | 15951 | ConstExprValue *slice_ptr = const_ptr_pointee(ira->codegen, &ptr_ptr->value); |
| ... | ... | @@ -15952,6 +15973,8 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio |
| 15952 | 15973 | abs_offset = 0; |
| 15953 | 15974 | rel_end = bigint_as_unsigned(&len_val->data.x_bigint); |
| 15954 | 15975 | break; |
| 15976 | case ConstPtrSpecialFunction: | |
| 15977 | zig_panic("TODO slice of slice cast from function"); | |
| 15955 | 15978 | } |
| 15956 | 15979 | } else { |
| 15957 | 15980 | zig_unreachable(); |
| ... | ... | @@ -16021,6 +16044,9 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio |
| 16021 | 16044 | parent_ptr->type->data.pointer.child_type, |
| 16022 | 16045 | parent_ptr->data.x_ptr.data.hard_coded_addr.addr + start_scalar, |
| 16023 | 16046 | slice_is_const(return_type)); |
| 16047 | break; | |
| 16048 | case ConstPtrSpecialFunction: | |
| 16049 | zig_panic("TODO"); | |
| 16024 | 16050 | } |
| 16025 | 16051 | |
| 16026 | 16052 | ConstExprValue *len_val = &out_val->data.x_struct.fields[slice_len_index]; |
test/cases/misc.zig+7| ... | ... | @@ -660,3 +660,10 @@ test "slicing zero length array" { |
| 660 | 660 | assert(mem.eql(u8, s1, "")); |
| 661 | 661 | assert(mem.eql(u32, s2, []u32{})); |
| 662 | 662 | } |
| 663 | ||
| 664 | ||
| 665 | const addr1 = @ptrCast(&const u8, emptyFn); | |
| 666 | test "comptime cast fn to ptr" { | |
| 667 | const addr2 = @ptrCast(&const u8, emptyFn); | |
| 668 | comptime assert(addr1 == addr2); | |
| 669 | } |