diff --git a/src/all_types.hpp b/src/all_types.hpp index ea54834fed..6afa7ccf20 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -144,6 +144,8 @@ enum ConstPtrSpecial { // This means that the pointer represents memory of assigning to _. // That is, storing discards the data, and loading is invalid. ConstPtrSpecialDiscard, + // This is actually a function. + ConstPtrSpecialFunction, }; enum ConstPtrMut { @@ -180,6 +182,9 @@ struct ConstPtrValue { struct { uint64_t addr; } hard_coded_addr; + struct { + FnTableEntry *fn_entry; + } fn; } data; }; @@ -222,10 +227,6 @@ enum RuntimeHintPtr { RuntimeHintPtrNonStack, }; -struct ConstFn { - FnTableEntry *fn_entry; -}; - struct ConstGlobalRefs { LLVMValueRef llvm_value; LLVMValueRef llvm_global; @@ -244,7 +245,6 @@ struct ConstExprValue { double x_f64; float128_t x_f128; bool x_bool; - ConstFn x_fn; ConstBoundFnValue x_bound_fn; TypeTableEntry *x_type; ConstExprValue *x_maybe; diff --git a/src/analyze.cpp b/src/analyze.cpp index aaf7c08bd8..89d9812311 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -4447,6 +4447,10 @@ static uint32_t hash_const_val(ConstExprValue *const_val) { case TypeTableEntryIdArgTuple: return (uint32_t)const_val->data.x_arg_tuple.start_index * (uint32_t)281907309 + (uint32_t)const_val->data.x_arg_tuple.end_index * (uint32_t)2290442768; + case TypeTableEntryIdFn: + assert(const_val->data.x_ptr.mut == ConstPtrMutComptimeConst); + assert(const_val->data.x_ptr.special == ConstPtrSpecialFunction); + return 3677364617 ^ hash_ptr(const_val->data.x_ptr.data.fn.fn_entry); case TypeTableEntryIdPointer: { uint32_t hash_val = 0; @@ -4486,6 +4490,10 @@ static uint32_t hash_const_val(ConstExprValue *const_val) { case ConstPtrSpecialDiscard: hash_val += 2010123162; return hash_val; + case ConstPtrSpecialFunction: + hash_val += (uint32_t)2590901619; + hash_val += hash_ptr(const_val->data.x_ptr.data.fn.fn_entry); + return hash_val; } zig_unreachable(); } @@ -4517,8 +4525,6 @@ static uint32_t hash_const_val(ConstExprValue *const_val) { case TypeTableEntryIdErrorSet: assert(const_val->data.x_err_set != nullptr); return const_val->data.x_err_set->value ^ 2630160122; - case TypeTableEntryIdFn: - return 4133894920 ^ hash_ptr(const_val->data.x_fn.fn_entry); case TypeTableEntryIdNamespace: return hash_ptr(const_val->data.x_import); case TypeTableEntryIdBlock: @@ -5150,8 +5156,6 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) { return true; case TypeTableEntryIdErrorSet: return a->data.x_err_set->value == b->data.x_err_set->value; - case TypeTableEntryIdFn: - return a->data.x_fn.fn_entry == b->data.x_fn.fn_entry; case TypeTableEntryIdBool: return a->data.x_bool == b->data.x_bool; case TypeTableEntryIdFloat: @@ -5172,6 +5176,7 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) { case TypeTableEntryIdNumLitInt: return bigint_cmp(&a->data.x_bigint, &b->data.x_bigint) == CmpEQ; case TypeTableEntryIdPointer: + case TypeTableEntryIdFn: if (a->data.x_ptr.special != b->data.x_ptr.special) return false; if (a->data.x_ptr.mut != b->data.x_ptr.mut) @@ -5211,6 +5216,8 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) { return true; case ConstPtrSpecialDiscard: return true; + case ConstPtrSpecialFunction: + return a->data.x_ptr.data.fn.fn_entry == b->data.x_ptr.data.fn.fn_entry; } zig_unreachable(); case TypeTableEntryIdArray: @@ -5371,6 +5378,14 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { buf_appendf(buf, "%s", value); return; } + case TypeTableEntryIdFn: + { + assert(const_val->data.x_ptr.mut == ConstPtrMutComptimeConst); + assert(const_val->data.x_ptr.special == ConstPtrSpecialFunction); + FnTableEntry *fn_entry = const_val->data.x_ptr.data.fn.fn_entry; + buf_appendf(buf, "%s", buf_ptr(&fn_entry->symbol_name)); + return; + } case TypeTableEntryIdPointer: switch (const_val->data.x_ptr.special) { case ConstPtrSpecialInvalid: @@ -5396,14 +5411,14 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { case ConstPtrSpecialDiscard: buf_append_str(buf, "&_"); return; + case ConstPtrSpecialFunction: + { + FnTableEntry *fn_entry = const_val->data.x_ptr.data.fn.fn_entry; + buf_appendf(buf, "@ptrCast(%s, %s)", buf_ptr(&const_val->type->name), buf_ptr(&fn_entry->symbol_name)); + return; + } } zig_unreachable(); - case TypeTableEntryIdFn: - { - FnTableEntry *fn_entry = const_val->data.x_fn.fn_entry; - buf_appendf(buf, "%s", buf_ptr(&fn_entry->symbol_name)); - return; - } case TypeTableEntryIdBlock: { AstNode *node = const_val->data.x_block->source_node; diff --git a/src/codegen.cpp b/src/codegen.cpp index 384322dac1..a44091bdbf 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -4840,7 +4840,9 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c case TypeTableEntryIdEnum: return bigint_to_llvm_const(type_entry->type_ref, &const_val->data.x_enum_tag); case TypeTableEntryIdFn: - return fn_llvm_value(g, const_val->data.x_fn.fn_entry); + assert(const_val->data.x_ptr.special == ConstPtrSpecialFunction); + assert(const_val->data.x_ptr.mut == ConstPtrMutComptimeConst); + return fn_llvm_value(g, const_val->data.x_ptr.data.fn.fn_entry); case TypeTableEntryIdPointer: { render_const_val_global(g, const_val, name); @@ -4909,6 +4911,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c render_const_val_global(g, const_val, ""); return const_val->global_refs->llvm_value; } + case ConstPtrSpecialFunction: + return LLVMConstBitCast(fn_llvm_value(g, const_val->data.x_ptr.data.fn.fn_entry), const_val->type->type_ref); } } zig_unreachable(); @@ -6313,7 +6317,9 @@ static void create_test_compile_var_and_add_test_runner(CodeGen *g) { ConstExprValue *fn_field = &this_val->data.x_struct.fields[1]; fn_field->type = fn_type; fn_field->special = ConstValSpecialStatic; - fn_field->data.x_fn.fn_entry = test_fn_entry; + fn_field->data.x_ptr.special = ConstPtrSpecialFunction; + fn_field->data.x_ptr.mut = ConstPtrMutComptimeConst; + fn_field->data.x_ptr.data.fn.fn_entry = test_fn_entry; } ConstExprValue *test_fn_slice = create_const_slice(g, test_fn_array, 0, g->test_fns.length, true); diff --git a/src/ir.cpp b/src/ir.cpp index 553fbcbf06..51e1a0e93e 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -130,6 +130,8 @@ ConstExprValue *const_ptr_pointee(CodeGen *g, ConstExprValue *const_val) { zig_unreachable(); case ConstPtrSpecialDiscard: zig_unreachable(); + case ConstPtrSpecialFunction: + zig_unreachable(); } zig_unreachable(); } @@ -875,7 +877,9 @@ static IrInstruction *ir_create_const_fn(IrBuilder *irb, Scope *scope, AstNode * IrInstructionConst *const_instruction = ir_create_instruction(irb, scope, source_node); const_instruction->base.value.type = fn_entry->type_entry; const_instruction->base.value.special = ConstValSpecialStatic; - const_instruction->base.value.data.x_fn.fn_entry = fn_entry; + const_instruction->base.value.data.x_ptr.data.fn.fn_entry = fn_entry; + const_instruction->base.value.data.x_ptr.mut = ConstPtrMutComptimeConst; + const_instruction->base.value.data.x_ptr.special = ConstPtrSpecialFunction; return &const_instruction->base; } @@ -8723,7 +8727,8 @@ static FnTableEntry *ir_resolve_fn(IrAnalyze *ira, IrInstruction *fn_value) { if (!const_val) return nullptr; - return const_val->data.x_fn.fn_entry; + assert(const_val->data.x_ptr.special == ConstPtrSpecialFunction); + return const_val->data.x_ptr.data.fn.fn_entry; } 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 case TypeTableEntryIdUnreachable: zig_unreachable(); case TypeTableEntryIdFn: { - FnTableEntry *fn_entry = target->value.data.x_fn.fn_entry; + assert(target->value.data.x_ptr.special == ConstPtrSpecialFunction); + FnTableEntry *fn_entry = target->value.data.x_ptr.data.fn.fn_entry; CallingConvention cc = fn_entry->type_entry->data.fn.fn_type_id.cc; switch (cc) { case CallingConventionUnspecified: { @@ -12852,6 +12858,8 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc zig_panic("TODO elem ptr on a const inner struct"); case ConstPtrSpecialHardCodedAddr: zig_unreachable(); + case ConstPtrSpecialFunction: + zig_panic("TODO element ptr of a function casted to a ptr"); } if (new_index >= mem_size) { 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 zig_panic("TODO elem ptr on a slice backed by const inner struct"); case ConstPtrSpecialHardCodedAddr: zig_unreachable(); + case ConstPtrSpecialFunction: + zig_panic("TODO elem ptr on a slice that was ptrcast from a function"); } return return_type; } else if (array_type->id == TypeTableEntryIdArray) { @@ -13101,7 +13111,9 @@ static TypeTableEntry *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source ConstExprValue *const_val = create_const_vals(1); const_val->special = ConstValSpecialStatic; const_val->type = fn_entry->type_entry; - const_val->data.x_fn.fn_entry = fn_entry; + const_val->data.x_ptr.data.fn.fn_entry = fn_entry; + const_val->data.x_ptr.special = ConstPtrSpecialFunction; + const_val->data.x_ptr.mut = ConstPtrMutComptimeConst; if (tld_fn->extern_lib_name != nullptr) { 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, fast_math_off_ptr = &block_scope->fast_math_off; fast_math_set_node_ptr = &block_scope->fast_math_set_node; } else if (target_type->id == TypeTableEntryIdFn) { - FnTableEntry *target_fn = target_val->data.x_fn.fn_entry; + assert(target_val->data.x_ptr.special == ConstPtrSpecialFunction); + FnTableEntry *target_fn = target_val->data.x_ptr.data.fn.fn_entry; assert(target_fn->def_scope); fast_math_off_ptr = &target_fn->def_scope->fast_math_off; 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 zig_panic("TODO memset on const inner struct"); case ConstPtrSpecialHardCodedAddr: zig_unreachable(); + case ConstPtrSpecialFunction: + zig_panic("TODO memset on ptr cast from function"); } 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 zig_panic("TODO memcpy on const inner struct"); case ConstPtrSpecialHardCodedAddr: zig_unreachable(); + case ConstPtrSpecialFunction: + zig_panic("TODO memcpy on ptr cast from function"); } if (dest_start + count > dest_end) { @@ -15803,6 +15820,8 @@ static TypeTableEntry *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructi zig_panic("TODO memcpy on const inner struct"); case ConstPtrSpecialHardCodedAddr: zig_unreachable(); + case ConstPtrSpecialFunction: + zig_panic("TODO memcpy on ptr cast from function"); } if (src_start + count > src_end) { @@ -15925,6 +15944,8 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio abs_offset = 0; rel_end = SIZE_MAX; break; + case ConstPtrSpecialFunction: + zig_panic("TODO slice of ptr cast from function"); } } else if (is_slice(array_type)) { ConstExprValue *slice_ptr = const_ptr_pointee(ira->codegen, &ptr_ptr->value); @@ -15952,6 +15973,8 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio abs_offset = 0; rel_end = bigint_as_unsigned(&len_val->data.x_bigint); break; + case ConstPtrSpecialFunction: + zig_panic("TODO slice of slice cast from function"); } } else { zig_unreachable(); @@ -16021,6 +16044,9 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio parent_ptr->type->data.pointer.child_type, parent_ptr->data.x_ptr.data.hard_coded_addr.addr + start_scalar, slice_is_const(return_type)); + break; + case ConstPtrSpecialFunction: + zig_panic("TODO"); } ConstExprValue *len_val = &out_val->data.x_struct.fields[slice_len_index]; diff --git a/test/cases/misc.zig b/test/cases/misc.zig index 905f11a848..95a9a46bff 100644 --- a/test/cases/misc.zig +++ b/test/cases/misc.zig @@ -660,3 +660,10 @@ test "slicing zero length array" { assert(mem.eql(u8, s1, "")); assert(mem.eql(u32, s2, []u32{})); } + + +const addr1 = @ptrCast(&const u8, emptyFn); +test "comptime cast fn to ptr" { + const addr2 = @ptrCast(&const u8, emptyFn); + comptime assert(addr1 == addr2); +}