Skip to content

Commit

Permalink
fix casting a function to a pointer causing compiler crash
Browse files Browse the repository at this point in the history
closes #777
  • Loading branch information
andrewrk committed Mar 13, 2018
1 parent d6e84e3 commit 7f7823e
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 22 deletions.
10 changes: 5 additions & 5 deletions src/all_types.hpp
Expand Up @@ -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 {
Expand Down Expand Up @@ -180,6 +182,9 @@ struct ConstPtrValue {
struct {
uint64_t addr;
} hard_coded_addr;
struct {
FnTableEntry *fn_entry;
} fn;
} data;
};

Expand Down Expand Up @@ -222,10 +227,6 @@ enum RuntimeHintPtr {
RuntimeHintPtrNonStack,
};

struct ConstFn {
FnTableEntry *fn_entry;
};

struct ConstGlobalRefs {
LLVMValueRef llvm_value;
LLVMValueRef llvm_global;
Expand All @@ -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;
Expand Down
35 changes: 25 additions & 10 deletions src/analyze.cpp
Expand Up @@ -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;
Expand Down Expand Up @@ -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();
}
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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:
Expand All @@ -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)
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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:
Expand All @@ -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;
Expand Down
10 changes: 8 additions & 2 deletions src/codegen.cpp
Expand Up @@ -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);
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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);
Expand Down
36 changes: 31 additions & 5 deletions src/ir.cpp
Expand Up @@ -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();
}
Expand Down Expand Up @@ -875,7 +877,9 @@ static IrInstruction *ir_create_const_fn(IrBuilder *irb, Scope *scope, AstNode *
IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(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;
}

Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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: {
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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];
Expand Down
7 changes: 7 additions & 0 deletions test/cases/misc.zig
Expand Up @@ -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);
}

0 comments on commit 7f7823e

Please sign in to comment.