From a05e224150a5a4bcad5ab1b399b43db8a0e28104 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 15 Feb 2019 19:19:28 -0500 Subject: typecheck the panic function this adds the prototype of panic to @import("builtin") and then uses it to do an implicit cast of the panic function to this prototype, rather than redoing all the implicit cast logic. closes #1894 closes #1895 --- src/all_types.hpp | 1 + src/analyze.cpp | 61 ++++++++++++++++++++----------------------------------- src/analyze.hpp | 1 + src/codegen.cpp | 4 ++++ src/ir.cpp | 15 ++++++++------ src/ir.hpp | 2 +- 6 files changed, 38 insertions(+), 46 deletions(-) (limited to 'src') diff --git a/src/all_types.hpp b/src/all_types.hpp index bafe316c3d..6fbd987b9e 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -1758,6 +1758,7 @@ struct CodeGen { ZigFn *cur_fn; ZigFn *main_fn; ZigFn *panic_fn; + TldFn *panic_tld_fn; AstNode *root_export_decl; CacheHash cache_hash; diff --git a/src/analyze.cpp b/src/analyze.cpp index 7949493586..12e245bd72 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -1351,7 +1351,7 @@ static ConstExprValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *no size_t backward_branch_count = 0; return ir_eval_const_value(g, scope, node, type_entry, &backward_branch_count, default_backward_branch_quota, - nullptr, nullptr, node, type_name, nullptr); + nullptr, nullptr, node, type_name, nullptr, nullptr); } ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node) { @@ -3247,36 +3247,19 @@ static bool scope_is_root_decls(Scope *scope) { zig_unreachable(); } -static void wrong_panic_prototype(CodeGen *g, AstNode *proto_node, ZigType *fn_type) { - add_node_error(g, proto_node, - buf_sprintf("expected 'fn([]const u8, ?*builtin.StackTrace) noreturn', found '%s'", - buf_ptr(&fn_type->name))); -} - -static void typecheck_panic_fn(CodeGen *g, ZigFn *panic_fn) { - AstNode *proto_node = panic_fn->proto_node; - assert(proto_node->type == NodeTypeFnProto); - ZigType *fn_type = panic_fn->type_entry; - FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id; - if (fn_type_id->param_count != 2) { - return wrong_panic_prototype(g, proto_node, fn_type); - } - ZigType *const_u8_ptr = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false, - PtrLenUnknown, 0, 0, 0); - ZigType *const_u8_slice = get_slice_type(g, const_u8_ptr); - if (fn_type_id->param_info[0].type != const_u8_slice) { - return wrong_panic_prototype(g, proto_node, fn_type); - } +void typecheck_panic_fn(CodeGen *g, TldFn *tld_fn, ZigFn *panic_fn) { + ConstExprValue *panic_fn_type_val = get_builtin_value(g, "PanicFn"); + assert(panic_fn_type_val != nullptr); + assert(panic_fn_type_val->type->id == ZigTypeIdMetaType); + ZigType *panic_fn_type = panic_fn_type_val->data.x_type; - ZigType *optional_ptr_to_stack_trace_type = get_optional_type(g, get_ptr_to_stack_trace_type(g)); - if (fn_type_id->param_info[1].type != optional_ptr_to_stack_trace_type) { - return wrong_panic_prototype(g, proto_node, fn_type); - } + AstNode *fake_decl = allocate(1); + *fake_decl = *panic_fn->proto_node; + fake_decl->type = NodeTypeSymbol; + fake_decl->data.symbol_expr.symbol = &panic_fn->symbol_name; - ZigType *actual_return_type = fn_type_id->return_type; - if (actual_return_type != g->builtin_types.entry_unreachable) { - return wrong_panic_prototype(g, proto_node, fn_type); - } + // call this for the side effects of casting to panic_fn_type + analyze_const_value(g, tld_fn->base.parent_scope, fake_decl, panic_fn_type, nullptr); } ZigType *get_test_fn_type(CodeGen *g) { @@ -3371,18 +3354,18 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) { if (!fn_table_entry->type_entry->data.fn.is_generic) { if (fn_def_node) g->fn_defs.append(fn_table_entry); + } - if (scope_is_root_decls(tld_fn->base.parent_scope) && - (import == g->root_import || import->package == g->panic_package)) + if (scope_is_root_decls(tld_fn->base.parent_scope) && + (import == g->root_import || import->package == g->panic_package)) + { + if (g->have_pub_main && buf_eql_str(&fn_table_entry->symbol_name, "main")) { + g->main_fn = fn_table_entry; + } else if ((import->package == g->panic_package || g->have_pub_panic) && + buf_eql_str(&fn_table_entry->symbol_name, "panic")) { - if (g->have_pub_main && buf_eql_str(&fn_table_entry->symbol_name, "main")) { - g->main_fn = fn_table_entry; - } else if ((import->package == g->panic_package || g->have_pub_panic) && - buf_eql_str(&fn_table_entry->symbol_name, "panic")) - { - g->panic_fn = fn_table_entry; - typecheck_panic_fn(g, fn_table_entry); - } + g->panic_fn = fn_table_entry; + g->panic_tld_fn = tld_fn; } } } else if (source_node->type == NodeTypeTestDecl) { diff --git a/src/analyze.hpp b/src/analyze.hpp index 7ded651e95..956ef47309 100644 --- a/src/analyze.hpp +++ b/src/analyze.hpp @@ -239,4 +239,5 @@ OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry); Error ensure_const_val_repr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node, ConstExprValue *const_val, ZigType *wanted_type); +void typecheck_panic_fn(CodeGen *g, TldFn *tld_fn, ZigFn *panic_fn); #endif diff --git a/src/codegen.cpp b/src/codegen.cpp index d2662b10d2..d2b2836b0c 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -7144,6 +7144,8 @@ Buf *codegen_generate_builtin_source(CodeGen *g) { " instruction_addresses: []usize,\n" "};\n\n"); + buf_append_str(contents, "pub const PanicFn = fn([]const u8, ?*StackTrace) noreturn;\n\n"); + const char *cur_os = nullptr; { buf_appendf(contents, "pub const Os = enum {\n"); @@ -7913,6 +7915,8 @@ static void gen_root_source(CodeGen *g) { } } + typecheck_panic_fn(g, g->panic_tld_fn, g->panic_fn); + report_errors_and_maybe_exit(g); } diff --git a/src/ir.cpp b/src/ir.cpp index 92cdd8c891..0fcbb60fe8 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -9949,7 +9949,7 @@ static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, Un ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, ZigType *expected_type, size_t *backward_branch_count, size_t backward_branch_quota, ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name, - IrExecutable *parent_exec) + IrExecutable *parent_exec, AstNode *expected_type_source_node) { if (expected_type != nullptr && type_is_invalid(expected_type)) return &codegen->invalid_instruction->value; @@ -9985,7 +9985,7 @@ ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *nod analyzed_executable->backward_branch_count = backward_branch_count; analyzed_executable->backward_branch_quota = backward_branch_quota; analyzed_executable->begin_scope = scope; - ZigType *result_type = ir_analyze(codegen, ir_executable, analyzed_executable, expected_type, node); + ZigType *result_type = ir_analyze(codegen, ir_executable, analyzed_executable, expected_type, expected_type_source_node); if (type_is_invalid(result_type)) return &codegen->invalid_instruction->value; @@ -10863,10 +10863,13 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa } break; } + case ConstCastResultIdFnIsGeneric: + add_error_note(ira->codegen, parent_msg, source_node, + buf_sprintf("only one of the functions is generic")); + break; case ConstCastResultIdFnAlign: // TODO case ConstCastResultIdFnCC: // TODO case ConstCastResultIdFnVarArgs: // TODO - case ConstCastResultIdFnIsGeneric: // TODO case ConstCastResultIdFnReturnType: // TODO case ConstCastResultIdFnArgCount: // TODO case ConstCastResultIdFnGenericArgCount: // TODO @@ -13856,7 +13859,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call AstNode *body_node = fn_entry->body_node; result = ir_eval_const_value(ira->codegen, exec_scope, body_node, return_type, ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, fn_entry, - nullptr, call_instruction->base.source_node, nullptr, ira->new_irb.exec); + nullptr, call_instruction->base.source_node, nullptr, ira->new_irb.exec, return_type_node); if (inferred_err_set_type != nullptr) { inferred_err_set_type->data.error_set.infer_fn = nullptr; @@ -14052,7 +14055,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call ConstExprValue *align_result = ir_eval_const_value(ira->codegen, impl_fn->child_scope, fn_proto_node->data.fn_proto.align_expr, get_align_amt_type(ira->codegen), ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, - nullptr, nullptr, fn_proto_node->data.fn_proto.align_expr, nullptr, ira->new_irb.exec); + nullptr, nullptr, fn_proto_node->data.fn_proto.align_expr, nullptr, ira->new_irb.exec, nullptr); IrInstructionConst *const_instruction = ir_create_instruction(&ira->new_irb, impl_fn->child_scope, fn_proto_node->data.fn_proto.align_expr); const_instruction->base.value = *align_result; @@ -18464,7 +18467,7 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct ZigType *void_type = ira->codegen->builtin_types.entry_void; ConstExprValue *cimport_result = ir_eval_const_value(ira->codegen, &cimport_scope->base, block_node, void_type, ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, nullptr, - &cimport_scope->buf, block_node, nullptr, nullptr); + &cimport_scope->buf, block_node, nullptr, nullptr, nullptr); if (type_is_invalid(cimport_result->type)) return ira->codegen->invalid_instruction; diff --git a/src/ir.hpp b/src/ir.hpp index 0a7c614812..0b85ad2c55 100644 --- a/src/ir.hpp +++ b/src/ir.hpp @@ -16,7 +16,7 @@ bool ir_gen_fn(CodeGen *g, ZigFn *fn_entry); ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, ZigType *expected_type, size_t *backward_branch_count, size_t backward_branch_quota, ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name, - IrExecutable *parent_exec); + IrExecutable *parent_exec, AstNode *expected_type_source_node); ZigType *ir_analyze(CodeGen *g, IrExecutable *old_executable, IrExecutable *new_executable, ZigType *expected_type, AstNode *expected_type_source_node); -- cgit v1.2.3