Skip to content

Commit 7f7823e

Browse files
committedMar 13, 2018
fix casting a function to a pointer causing compiler crash
closes #777
1 parent d6e84e3 commit 7f7823e

File tree

5 files changed

+76
-22
lines changed

5 files changed

+76
-22
lines changed
 

‎src/all_types.hpp

+5-5
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,8 @@ enum ConstPtrSpecial {
144144
// This means that the pointer represents memory of assigning to _.
145145
// That is, storing discards the data, and loading is invalid.
146146
ConstPtrSpecialDiscard,
147+
// This is actually a function.
148+
ConstPtrSpecialFunction,
147149
};
148150

149151
enum ConstPtrMut {
@@ -180,6 +182,9 @@ struct ConstPtrValue {
180182
struct {
181183
uint64_t addr;
182184
} hard_coded_addr;
185+
struct {
186+
FnTableEntry *fn_entry;
187+
} fn;
183188
} data;
184189
};
185190

@@ -222,10 +227,6 @@ enum RuntimeHintPtr {
222227
RuntimeHintPtrNonStack,
223228
};
224229

225-
struct ConstFn {
226-
FnTableEntry *fn_entry;
227-
};
228-
229230
struct ConstGlobalRefs {
230231
LLVMValueRef llvm_value;
231232
LLVMValueRef llvm_global;
@@ -244,7 +245,6 @@ struct ConstExprValue {
244245
double x_f64;
245246
float128_t x_f128;
246247
bool x_bool;
247-
ConstFn x_fn;
248248
ConstBoundFnValue x_bound_fn;
249249
TypeTableEntry *x_type;
250250
ConstExprValue *x_maybe;

‎src/analyze.cpp

+25-10
Original file line numberDiff line numberDiff line change
@@ -4447,6 +4447,10 @@ static uint32_t hash_const_val(ConstExprValue *const_val) {
44474447
case TypeTableEntryIdArgTuple:
44484448
return (uint32_t)const_val->data.x_arg_tuple.start_index * (uint32_t)281907309 +
44494449
(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);
44504454
case TypeTableEntryIdPointer:
44514455
{
44524456
uint32_t hash_val = 0;
@@ -4486,6 +4490,10 @@ static uint32_t hash_const_val(ConstExprValue *const_val) {
44864490
case ConstPtrSpecialDiscard:
44874491
hash_val += 2010123162;
44884492
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;
44894497
}
44904498
zig_unreachable();
44914499
}
@@ -4517,8 +4525,6 @@ static uint32_t hash_const_val(ConstExprValue *const_val) {
45174525
case TypeTableEntryIdErrorSet:
45184526
assert(const_val->data.x_err_set != nullptr);
45194527
return const_val->data.x_err_set->value ^ 2630160122;
4520-
case TypeTableEntryIdFn:
4521-
return 4133894920 ^ hash_ptr(const_val->data.x_fn.fn_entry);
45224528
case TypeTableEntryIdNamespace:
45234529
return hash_ptr(const_val->data.x_import);
45244530
case TypeTableEntryIdBlock:
@@ -5150,8 +5156,6 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) {
51505156
return true;
51515157
case TypeTableEntryIdErrorSet:
51525158
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;
51555159
case TypeTableEntryIdBool:
51565160
return a->data.x_bool == b->data.x_bool;
51575161
case TypeTableEntryIdFloat:
@@ -5172,6 +5176,7 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) {
51725176
case TypeTableEntryIdNumLitInt:
51735177
return bigint_cmp(&a->data.x_bigint, &b->data.x_bigint) == CmpEQ;
51745178
case TypeTableEntryIdPointer:
5179+
case TypeTableEntryIdFn:
51755180
if (a->data.x_ptr.special != b->data.x_ptr.special)
51765181
return false;
51775182
if (a->data.x_ptr.mut != b->data.x_ptr.mut)
@@ -5211,6 +5216,8 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) {
52115216
return true;
52125217
case ConstPtrSpecialDiscard:
52135218
return true;
5219+
case ConstPtrSpecialFunction:
5220+
return a->data.x_ptr.data.fn.fn_entry == b->data.x_ptr.data.fn.fn_entry;
52145221
}
52155222
zig_unreachable();
52165223
case TypeTableEntryIdArray:
@@ -5371,6 +5378,14 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
53715378
buf_appendf(buf, "%s", value);
53725379
return;
53735380
}
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+
}
53745389
case TypeTableEntryIdPointer:
53755390
switch (const_val->data.x_ptr.special) {
53765391
case ConstPtrSpecialInvalid:
@@ -5396,14 +5411,14 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
53965411
case ConstPtrSpecialDiscard:
53975412
buf_append_str(buf, "&_");
53985413
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+
}
53995420
}
54005421
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-
}
54075422
case TypeTableEntryIdBlock:
54085423
{
54095424
AstNode *node = const_val->data.x_block->source_node;

‎src/codegen.cpp

+8-2
Original file line numberDiff line numberDiff line change
@@ -4840,7 +4840,9 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
48404840
case TypeTableEntryIdEnum:
48414841
return bigint_to_llvm_const(type_entry->type_ref, &const_val->data.x_enum_tag);
48424842
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);
48444846
case TypeTableEntryIdPointer:
48454847
{
48464848
render_const_val_global(g, const_val, name);
@@ -4909,6 +4911,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
49094911
render_const_val_global(g, const_val, "");
49104912
return const_val->global_refs->llvm_value;
49114913
}
4914+
case ConstPtrSpecialFunction:
4915+
return LLVMConstBitCast(fn_llvm_value(g, const_val->data.x_ptr.data.fn.fn_entry), const_val->type->type_ref);
49124916
}
49134917
}
49144918
zig_unreachable();
@@ -6313,7 +6317,9 @@ static void create_test_compile_var_and_add_test_runner(CodeGen *g) {
63136317
ConstExprValue *fn_field = &this_val->data.x_struct.fields[1];
63146318
fn_field->type = fn_type;
63156319
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;
63176323
}
63186324

63196325
ConstExprValue *test_fn_slice = create_const_slice(g, test_fn_array, 0, g->test_fns.length, true);

‎src/ir.cpp

+31-5
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,8 @@ ConstExprValue *const_ptr_pointee(CodeGen *g, ConstExprValue *const_val) {
130130
zig_unreachable();
131131
case ConstPtrSpecialDiscard:
132132
zig_unreachable();
133+
case ConstPtrSpecialFunction:
134+
zig_unreachable();
133135
}
134136
zig_unreachable();
135137
}
@@ -875,7 +877,9 @@ static IrInstruction *ir_create_const_fn(IrBuilder *irb, Scope *scope, AstNode *
875877
IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(irb, scope, source_node);
876878
const_instruction->base.value.type = fn_entry->type_entry;
877879
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;
879883
return &const_instruction->base;
880884
}
881885

@@ -8723,7 +8727,8 @@ static FnTableEntry *ir_resolve_fn(IrAnalyze *ira, IrInstruction *fn_value) {
87238727
if (!const_val)
87248728
return nullptr;
87258729

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;
87278732
}
87288733

87298734
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
1131111316
case TypeTableEntryIdUnreachable:
1131211317
zig_unreachable();
1131311318
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;
1131511321
CallingConvention cc = fn_entry->type_entry->data.fn.fn_type_id.cc;
1131611322
switch (cc) {
1131711323
case CallingConventionUnspecified: {
@@ -12852,6 +12858,8 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc
1285212858
zig_panic("TODO elem ptr on a const inner struct");
1285312859
case ConstPtrSpecialHardCodedAddr:
1285412860
zig_unreachable();
12861+
case ConstPtrSpecialFunction:
12862+
zig_panic("TODO element ptr of a function casted to a ptr");
1285512863
}
1285612864
if (new_index >= mem_size) {
1285712865
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
1290112909
zig_panic("TODO elem ptr on a slice backed by const inner struct");
1290212910
case ConstPtrSpecialHardCodedAddr:
1290312911
zig_unreachable();
12912+
case ConstPtrSpecialFunction:
12913+
zig_panic("TODO elem ptr on a slice that was ptrcast from a function");
1290412914
}
1290512915
return return_type;
1290612916
} else if (array_type->id == TypeTableEntryIdArray) {
@@ -13101,7 +13111,9 @@ static TypeTableEntry *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source
1310113111
ConstExprValue *const_val = create_const_vals(1);
1310213112
const_val->special = ConstValSpecialStatic;
1310313113
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;
1310513117

1310613118
if (tld_fn->extern_lib_name != nullptr) {
1310713119
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,
1377113783
fast_math_off_ptr = &block_scope->fast_math_off;
1377213784
fast_math_set_node_ptr = &block_scope->fast_math_set_node;
1377313785
} 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;
1377513788
assert(target_fn->def_scope);
1377613789
fast_math_off_ptr = &target_fn->def_scope->fast_math_off;
1377713790
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
1567315686
zig_panic("TODO memset on const inner struct");
1567415687
case ConstPtrSpecialHardCodedAddr:
1567515688
zig_unreachable();
15689+
case ConstPtrSpecialFunction:
15690+
zig_panic("TODO memset on ptr cast from function");
1567615691
}
1567715692

1567815693
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
1576915784
zig_panic("TODO memcpy on const inner struct");
1577015785
case ConstPtrSpecialHardCodedAddr:
1577115786
zig_unreachable();
15787+
case ConstPtrSpecialFunction:
15788+
zig_panic("TODO memcpy on ptr cast from function");
1577215789
}
1577315790

1577415791
if (dest_start + count > dest_end) {
@@ -15803,6 +15820,8 @@ static TypeTableEntry *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructi
1580315820
zig_panic("TODO memcpy on const inner struct");
1580415821
case ConstPtrSpecialHardCodedAddr:
1580515822
zig_unreachable();
15823+
case ConstPtrSpecialFunction:
15824+
zig_panic("TODO memcpy on ptr cast from function");
1580615825
}
1580715826

1580815827
if (src_start + count > src_end) {
@@ -15925,6 +15944,8 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio
1592515944
abs_offset = 0;
1592615945
rel_end = SIZE_MAX;
1592715946
break;
15947+
case ConstPtrSpecialFunction:
15948+
zig_panic("TODO slice of ptr cast from function");
1592815949
}
1592915950
} else if (is_slice(array_type)) {
1593015951
ConstExprValue *slice_ptr = const_ptr_pointee(ira->codegen, &ptr_ptr->value);
@@ -15952,6 +15973,8 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio
1595215973
abs_offset = 0;
1595315974
rel_end = bigint_as_unsigned(&len_val->data.x_bigint);
1595415975
break;
15976+
case ConstPtrSpecialFunction:
15977+
zig_panic("TODO slice of slice cast from function");
1595515978
}
1595615979
} else {
1595715980
zig_unreachable();
@@ -16021,6 +16044,9 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio
1602116044
parent_ptr->type->data.pointer.child_type,
1602216045
parent_ptr->data.x_ptr.data.hard_coded_addr.addr + start_scalar,
1602316046
slice_is_const(return_type));
16047+
break;
16048+
case ConstPtrSpecialFunction:
16049+
zig_panic("TODO");
1602416050
}
1602516051

1602616052
ConstExprValue *len_val = &out_val->data.x_struct.fields[slice_len_index];

‎test/cases/misc.zig

+7
Original file line numberDiff line numberDiff line change
@@ -660,3 +660,10 @@ test "slicing zero length array" {
660660
assert(mem.eql(u8, s1, ""));
661661
assert(mem.eql(u32, s2, []u32{}));
662662
}
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+
}

0 commit comments

Comments
 (0)
Please sign in to comment.