diff options
Diffstat (limited to 'src/analyze.cpp')
| -rw-r--r-- | src/analyze.cpp | 1307 |
1 files changed, 2 insertions, 1305 deletions
diff --git a/src/analyze.cpp b/src/analyze.cpp index 0bb212f8d1..451b259e24 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -1067,76 +1067,6 @@ static TypeTableEntry *analyze_fn_proto_type(CodeGen *g, ImportTableEntry *impor return get_fn_type(g, &fn_type_id, gen_debug_info); } -static Buf *resolve_const_expr_str(CodeGen *g, ImportTableEntry *import, BlockContext *context, AstNode **node) { - TypeTableEntry *str_type = get_slice_type(g, g->builtin_types.entry_u8, true); - TypeTableEntry *resolved_type = analyze_expression(g, import, context, str_type, *node); - - if (resolved_type->id == TypeTableEntryIdInvalid) { - return nullptr; - } - - ConstExprValue *const_str_val = &get_resolved_expr(*node)->const_val; - - if (!const_str_val->ok) { - add_node_error(g, *node, buf_sprintf("unable to evaluate constant expression")); - return nullptr; - } - - ConstExprValue *ptr_field = const_str_val->data.x_struct.fields[0]; - uint64_t len = ptr_field->data.x_ptr.len; - Buf *result = buf_alloc(); - for (uint64_t i = 0; i < len; i += 1) { - ConstExprValue *char_val = ptr_field->data.x_ptr.ptr[i]; - uint64_t big_c = char_val->data.x_bignum.data.x_uint; - assert(big_c <= UINT8_MAX); - uint8_t c = big_c; - buf_append_char(result, c); - } - return result; -} - -static bool resolve_const_expr_bool(CodeGen *g, ImportTableEntry *import, BlockContext *context, - AstNode **node, bool *value) -{ - TypeTableEntry *resolved_type = analyze_expression(g, import, context, g->builtin_types.entry_bool, *node); - - if (resolved_type->id == TypeTableEntryIdInvalid) { - return false; - } - - ConstExprValue *const_bool_val = &get_resolved_expr(*node)->const_val; - - if (!const_bool_val->ok) { - add_node_error(g, *node, buf_sprintf("unable to evaluate constant expression")); - return false; - } - - *value = const_bool_val->data.x_bool; - return true; -} - -static FnTableEntry *resolve_const_expr_fn(CodeGen *g, ImportTableEntry *import, BlockContext *context, - AstNode **node) -{ - TypeTableEntry *resolved_type = analyze_expression(g, import, context, nullptr, *node); - - if (resolved_type->id == TypeTableEntryIdInvalid) { - return nullptr; - } else if (resolved_type->id == TypeTableEntryIdFn) { - ConstExprValue *const_val = &get_resolved_expr(*node)->const_val; - - if (!const_val->ok) { - add_node_error(g, *node, buf_sprintf("unable to evaluate constant expression")); - return nullptr; - } - - return const_val->data.x_fn; - } else { - add_node_error(g, *node, buf_sprintf("expected function, got '%s'", buf_ptr(&resolved_type->name))); - return nullptr; - } -} - static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_table_entry, ImportTableEntry *import, BlockContext *containing_context) { @@ -3073,16 +3003,6 @@ static TypeTableEntry *resolve_expr_const_val_as_bool(CodeGen *g, AstNode *node, return g->builtin_types.entry_bool; } -static TypeTableEntry *resolve_expr_const_val_as_non_null(CodeGen *g, AstNode *node, - TypeTableEntry *type, ConstExprValue *other_val) -{ - assert(other_val->ok); - Expr *expr = get_resolved_expr(node); - expr->const_val.ok = true; - expr->const_val.data.x_maybe = other_val; - return type; -} - static TypeTableEntry *resolve_expr_const_val_as_c_string_lit(CodeGen *g, AstNode *node, Buf *str) { Expr *expr = get_resolved_expr(node); expr->const_val.ok = true; @@ -4432,33 +4352,6 @@ static TypeTableEntry *analyze_if_var_expr(CodeGen *g, ImportTableEntry *import, node, then_node, else_node, cond_is_const, cond_bool_val); } -static TypeTableEntry *analyze_min_max_value(CodeGen *g, ImportTableEntry *import, BlockContext *context, - AstNode *node, const char *err_format, bool is_max) -{ - assert(node->type == NodeTypeFnCallExpr); - assert(node->data.fn_call_expr.params.length == 1); - - AstNode *type_node = node->data.fn_call_expr.params.at(0); - TypeTableEntry *type_entry = analyze_type_expr(g, import, context, type_node); - - if (type_entry->id == TypeTableEntryIdInvalid) { - return g->builtin_types.entry_invalid; - } else if (type_entry->id == TypeTableEntryIdInt) { - eval_min_max_value(g, type_entry, &get_resolved_expr(node)->const_val, is_max); - return g->builtin_types.entry_num_lit_int; - } else if (type_entry->id == TypeTableEntryIdFloat) { - eval_min_max_value(g, type_entry, &get_resolved_expr(node)->const_val, is_max); - return g->builtin_types.entry_num_lit_float; - } else if (type_entry->id == TypeTableEntryIdBool) { - eval_min_max_value(g, type_entry, &get_resolved_expr(node)->const_val, is_max); - return type_entry; - } else { - add_node_error(g, node, - buf_sprintf(err_format, buf_ptr(&type_entry->name))); - return g->builtin_types.entry_invalid; - } -} - bool type_is_codegen_pointer(TypeTableEntry *type) { if (type->id == TypeTableEntryIdPointer) return true; if (type->id == TypeTableEntryIdFn) return true; @@ -4469,986 +4362,6 @@ bool type_is_codegen_pointer(TypeTableEntry *type) { return false; } -static TypeTableEntry *analyze_import(CodeGen *g, ImportTableEntry *import, BlockContext *context, - AstNode *node) -{ - assert(node->type == NodeTypeFnCallExpr); - - if (context->fn_entry) { - add_node_error(g, node, buf_sprintf("@import invalid inside function bodies")); - return g->builtin_types.entry_invalid; - } - - AstNode *first_param_node = node->data.fn_call_expr.params.at(0); - Buf *import_target_str = resolve_const_expr_str(g, import, context, first_param_node->parent_field); - if (!import_target_str) { - return g->builtin_types.entry_invalid; - } - - Buf *import_target_path; - Buf *search_dir; - assert(import->package); - PackageTableEntry *target_package; - auto package_entry = import->package->package_table.maybe_get(import_target_str); - if (package_entry) { - target_package = package_entry->value; - import_target_path = &target_package->root_src_path; - search_dir = &target_package->root_src_dir; - } else { - // try it as a filename - target_package = import->package; - import_target_path = import_target_str; - search_dir = &import->package->root_src_dir; - } - - Buf full_path = BUF_INIT; - os_path_join(search_dir, import_target_path, &full_path); - - Buf *import_code = buf_alloc(); - Buf *abs_full_path = buf_alloc(); - int err; - if ((err = os_path_real(&full_path, abs_full_path))) { - if (err == ErrorFileNotFound) { - add_node_error(g, node, - buf_sprintf("unable to find '%s'", buf_ptr(import_target_path))); - return g->builtin_types.entry_invalid; - } else { - g->error_during_imports = true; - add_node_error(g, node, - buf_sprintf("unable to open '%s': %s", buf_ptr(&full_path), err_str(err))); - return g->builtin_types.entry_invalid; - } - } - - auto import_entry = g->import_table.maybe_get(abs_full_path); - if (import_entry) { - return resolve_expr_const_val_as_import(g, node, import_entry->value); - } - - if ((err = os_fetch_file_path(abs_full_path, import_code))) { - if (err == ErrorFileNotFound) { - add_node_error(g, node, - buf_sprintf("unable to find '%s'", buf_ptr(import_target_path))); - return g->builtin_types.entry_invalid; - } else { - add_node_error(g, node, - buf_sprintf("unable to open '%s': %s", buf_ptr(&full_path), err_str(err))); - return g->builtin_types.entry_invalid; - } - } - ImportTableEntry *target_import = add_source_file(g, target_package, - abs_full_path, search_dir, import_target_path, import_code); - - scan_decls(g, target_import, target_import->block_context, target_import->root); - - return resolve_expr_const_val_as_import(g, node, target_import); -} - -static TypeTableEntry *analyze_c_import(CodeGen *g, ImportTableEntry *parent_import, - BlockContext *parent_context, AstNode *node) -{ - assert(node->type == NodeTypeFnCallExpr); - - if (parent_context->fn_entry) { - add_node_error(g, node, buf_sprintf("@c_import invalid inside function bodies")); - return g->builtin_types.entry_invalid; - } - - AstNode *block_node = node->data.fn_call_expr.params.at(0); - - BlockContext *child_context = new_block_context(node, parent_context); - child_context->c_import_buf = buf_alloc(); - - TypeTableEntry *resolved_type = analyze_expression(g, parent_import, child_context, - g->builtin_types.entry_void, block_node); - - if (resolved_type->id == TypeTableEntryIdInvalid) { - return resolved_type; - } - - find_libc_include_path(g); - - ImportTableEntry *child_import = allocate<ImportTableEntry>(1); - child_import->c_import_node = node; - - ZigList<ErrorMsg *> errors = {0}; - - int err; - if ((err = parse_h_buf(child_import, &errors, child_context->c_import_buf, g, node))) { - zig_panic("unable to parse h file: %s\n", err_str(err)); - } - - if (errors.length > 0) { - ErrorMsg *parent_err_msg = add_node_error(g, node, buf_sprintf("C import failed")); - for (size_t i = 0; i < errors.length; i += 1) { - ErrorMsg *err_msg = errors.at(i); - err_msg_add_note(parent_err_msg, err_msg); - } - - return g->builtin_types.entry_invalid; - } - - if (g->verbose) { - fprintf(stderr, "\nc_import:\n"); - fprintf(stderr, "-----------\n"); - ast_render(stderr, child_import->root, 4); - } - - child_import->di_file = parent_import->di_file; - child_import->block_context = new_block_context(child_import->root, nullptr); - - scan_decls(g, child_import, child_import->block_context, child_import->root); - return resolve_expr_const_val_as_import(g, node, child_import); -} - -static TypeTableEntry *analyze_err_name(CodeGen *g, ImportTableEntry *import, - BlockContext *context, AstNode *node) -{ - assert(node->type == NodeTypeFnCallExpr); - - AstNode *err_value = node->data.fn_call_expr.params.at(0); - TypeTableEntry *resolved_type = analyze_expression(g, import, context, - g->builtin_types.entry_pure_error, err_value); - - if (resolved_type->id == TypeTableEntryIdInvalid) { - return resolved_type; - } - - g->generate_error_name_table = true; - - TypeTableEntry *str_type = get_slice_type(g, g->builtin_types.entry_u8, true); - return str_type; -} - -static TypeTableEntry *analyze_embed_file(CodeGen *g, ImportTableEntry *import, - BlockContext *context, AstNode *node) -{ - assert(node->type == NodeTypeFnCallExpr); - - AstNode **first_param_node = &node->data.fn_call_expr.params.at(0); - Buf *rel_file_path = resolve_const_expr_str(g, import, context, first_param_node); - if (!rel_file_path) { - return g->builtin_types.entry_invalid; - } - - // figure out absolute path to resource - Buf source_dir_path = BUF_INIT; - os_path_dirname(import->path, &source_dir_path); - - Buf file_path = BUF_INIT; - os_path_resolve(&source_dir_path, rel_file_path, &file_path); - - // load from file system into const expr - Buf file_contents = BUF_INIT; - int err; - if ((err = os_fetch_file_path(&file_path, &file_contents))) { - if (err == ErrorFileNotFound) { - add_node_error(g, node, - buf_sprintf("unable to find '%s'", buf_ptr(&file_path))); - return g->builtin_types.entry_invalid; - } else { - add_node_error(g, node, - buf_sprintf("unable to open '%s': %s", buf_ptr(&file_path), err_str(err))); - return g->builtin_types.entry_invalid; - } - } - - // TODO add dependency on the file we embedded so that we know if it changes - // we'll have to invalidate the cache - - return resolve_expr_const_val_as_string_lit(g, node, &file_contents); -} - -static TypeTableEntry *analyze_cmpxchg(CodeGen *g, ImportTableEntry *import, - BlockContext *context, AstNode *node) -{ - assert(node->type == NodeTypeFnCallExpr); - - AstNode **ptr_arg = &node->data.fn_call_expr.params.at(0); - AstNode **cmp_arg = &node->data.fn_call_expr.params.at(1); - AstNode **new_arg = &node->data.fn_call_expr.params.at(2); - AstNode **success_order_arg = &node->data.fn_call_expr.params.at(3); - AstNode **failure_order_arg = &node->data.fn_call_expr.params.at(4); - - TypeTableEntry *ptr_type = analyze_expression(g, import, context, nullptr, *ptr_arg); - if (ptr_type->id == TypeTableEntryIdInvalid) { - return g->builtin_types.entry_invalid; - } else if (ptr_type->id != TypeTableEntryIdPointer) { - add_node_error(g, *ptr_arg, - buf_sprintf("expected pointer argument, got '%s'", buf_ptr(&ptr_type->name))); - return g->builtin_types.entry_invalid; - } - - TypeTableEntry *child_type = ptr_type->data.pointer.child_type; - TypeTableEntry *cmp_type = analyze_expression(g, import, context, child_type, *cmp_arg); - TypeTableEntry *new_type = analyze_expression(g, import, context, child_type, *new_arg); - - TypeTableEntry *success_order_type = analyze_expression(g, import, context, - g->builtin_types.entry_atomic_order_enum, *success_order_arg); - TypeTableEntry *failure_order_type = analyze_expression(g, import, context, - g->builtin_types.entry_atomic_order_enum, *failure_order_arg); - - if (cmp_type->id == TypeTableEntryIdInvalid || - new_type->id == TypeTableEntryIdInvalid || - success_order_type->id == TypeTableEntryIdInvalid || - failure_order_type->id == TypeTableEntryIdInvalid) - { - return g->builtin_types.entry_invalid; - } - - ConstExprValue *success_order_val = &get_resolved_expr(*success_order_arg)->const_val; - ConstExprValue *failure_order_val = &get_resolved_expr(*failure_order_arg)->const_val; - if (!success_order_val->ok) { - add_node_error(g, *success_order_arg, buf_sprintf("unable to evaluate constant expression")); - return g->builtin_types.entry_invalid; - } else if (!failure_order_val->ok) { - add_node_error(g, *failure_order_arg, buf_sprintf("unable to evaluate constant expression")); - return g->builtin_types.entry_invalid; - } - - if (success_order_val->data.x_enum.tag < AtomicOrderMonotonic) { - add_node_error(g, *success_order_arg, - buf_sprintf("success atomic ordering must be Monotonic or stricter")); - return g->builtin_types.entry_invalid; - } - if (failure_order_val->data.x_enum.tag < AtomicOrderMonotonic) { - add_node_error(g, *failure_order_arg, - buf_sprintf("failure atomic ordering must be Monotonic or stricter")); - return g->builtin_types.entry_invalid; - } - if (failure_order_val->data.x_enum.tag > success_order_val->data.x_enum.tag) { - add_node_error(g, *failure_order_arg, - buf_sprintf("failure atomic ordering must be no stricter than success")); - return g->builtin_types.entry_invalid; - } - if (failure_order_val->data.x_enum.tag == AtomicOrderRelease || - failure_order_val->data.x_enum.tag == AtomicOrderAcqRel) - { - add_node_error(g, *failure_order_arg, - buf_sprintf("failure atomic ordering must not be Release or AcqRel")); - return g->builtin_types.entry_invalid; - } - - return g->builtin_types.entry_bool; -} - -static TypeTableEntry *analyze_fence(CodeGen *g, ImportTableEntry *import, - BlockContext *context, AstNode *node) -{ - assert(node->type == NodeTypeFnCallExpr); - - AstNode **atomic_order_arg = &node->data.fn_call_expr.params.at(0); - TypeTableEntry *atomic_order_type = analyze_expression(g, import, context, - g->builtin_types.entry_atomic_order_enum, *atomic_order_arg); - - if (atomic_order_type->id == TypeTableEntryIdInvalid) { - return g->builtin_types.entry_invalid; - } - - ConstExprValue *atomic_order_val = &get_resolved_expr(*atomic_order_arg)->const_val; - - if (!atomic_order_val->ok) { - add_node_error(g, *atomic_order_arg, buf_sprintf("unable to evaluate constant expression")); - return g->builtin_types.entry_invalid; - } - - return g->builtin_types.entry_void; -} - -static TypeTableEntry *analyze_div_exact(CodeGen *g, ImportTableEntry *import, - BlockContext *context, AstNode *node) -{ - assert(node->type == NodeTypeFnCallExpr); - - AstNode **op1 = &node->data.fn_call_expr.params.at(0); - AstNode **op2 = &node->data.fn_call_expr.params.at(1); - - TypeTableEntry *op1_type = analyze_expression(g, import, context, nullptr, *op1); - TypeTableEntry *op2_type = analyze_expression(g, import, context, nullptr, *op2); - - AstNode *op_nodes[] = {*op1, *op2}; - TypeTableEntry *op_types[] = {op1_type, op2_type}; - TypeTableEntry *result_type = resolve_peer_type_compatibility(g, import, context, node, - op_nodes, op_types, 2); - - if (result_type->id == TypeTableEntryIdInvalid) { - return g->builtin_types.entry_invalid; - } else if (result_type->id == TypeTableEntryIdInt) { - return result_type; - } else if (result_type->id == TypeTableEntryIdNumLitInt) { - // check for division by zero - // check for non exact division - zig_panic("TODO"); - } else { - add_node_error(g, node, - buf_sprintf("expected integer type, got '%s'", buf_ptr(&result_type->name))); - return g->builtin_types.entry_invalid; - } -} - -static TypeTableEntry *analyze_truncate(CodeGen *g, ImportTableEntry *import, - BlockContext *context, AstNode *node) -{ - assert(node->type == NodeTypeFnCallExpr); - - AstNode **op1 = &node->data.fn_call_expr.params.at(0); - AstNode **op2 = &node->data.fn_call_expr.params.at(1); - - TypeTableEntry *dest_type = analyze_type_expr(g, import, context, *op1); - TypeTableEntry *src_type = analyze_expression(g, import, context, nullptr, *op2); - - if (dest_type->id == TypeTableEntryIdInvalid || src_type->id == TypeTableEntryIdInvalid) { - return g->builtin_types.entry_invalid; - } else if (dest_type->id != TypeTableEntryIdInt) { - add_node_error(g, *op1, - buf_sprintf("expected integer type, got '%s'", buf_ptr(&dest_type->name))); - return g->builtin_types.entry_invalid; - } else if (src_type->id != TypeTableEntryIdInt) { - add_node_error(g, *op2, - buf_sprintf("expected integer type, got '%s'", buf_ptr(&src_type->name))); - return g->builtin_types.entry_invalid; - } else if (src_type->data.integral.is_signed != dest_type->data.integral.is_signed) { - const char *sign_str = dest_type->data.integral.is_signed ? "signed" : "unsigned"; - add_node_error(g, *op2, - buf_sprintf("expected %s integer type, got '%s'", sign_str, buf_ptr(&src_type->name))); - return g->builtin_types.entry_invalid; - } else if (src_type->data.integral.bit_count <= dest_type->data.integral.bit_count) { - add_node_error(g, *op2, - buf_sprintf("type '%s' has same or fewer bits than destination type '%s'", - buf_ptr(&src_type->name), buf_ptr(&dest_type->name))); - return g->builtin_types.entry_invalid; - } - - // TODO const expr eval - - return dest_type; -} - -static TypeTableEntry *analyze_compile_err(CodeGen *g, ImportTableEntry *import, - BlockContext *context, AstNode *node) -{ - AstNode *first_param_node = node->data.fn_call_expr.params.at(0); - Buf *err_msg = resolve_const_expr_str(g, import, context, first_param_node->parent_field); - if (!err_msg) { - return g->builtin_types.entry_invalid; - } - - add_node_error(g, node, err_msg); - - return g->builtin_types.entry_invalid; -} - -static TypeTableEntry *analyze_int_type(CodeGen *g, ImportTableEntry *import, - BlockContext *context, AstNode *node) -{ - AstNode **is_signed_node = &node->data.fn_call_expr.params.at(0); - AstNode **bit_count_node = &node->data.fn_call_expr.params.at(1); - - TypeTableEntry *bool_type = g->builtin_types.entry_bool; - TypeTableEntry *usize_type = g->builtin_types.entry_usize; - TypeTableEntry *is_signed_type = analyze_expression(g, import, context, bool_type, *is_signed_node); - TypeTableEntry *bit_count_type = analyze_expression(g, import, context, usize_type, *bit_count_node); - - if (is_signed_type->id == TypeTableEntryIdInvalid || - bit_count_type->id == TypeTableEntryIdInvalid) - { - return g->builtin_types.entry_invalid; - } - - ConstExprValue *is_signed_val = &get_resolved_expr(*is_signed_node)->const_val; - ConstExprValue *bit_count_val = &get_resolved_expr(*bit_count_node)->const_val; - - AstNode *bad_node = nullptr; - if (!is_signed_val->ok) { - bad_node = *is_signed_node; - } else if (!bit_count_val->ok) { - bad_node = *bit_count_node; - } - if (bad_node) { - add_node_error(g, bad_node, buf_sprintf("unable to evaluate constant expression")); - return g->builtin_types.entry_invalid; - } - - bool depends_on_compile_var = is_signed_val->depends_on_compile_var || bit_count_val->depends_on_compile_var; - - TypeTableEntry *int_type = get_int_type(g, is_signed_val->data.x_bool, - bit_count_val->data.x_bignum.data.x_uint); - return resolve_expr_const_val_as_type(g, node, int_type, depends_on_compile_var); - -} - -static TypeTableEntry *analyze_set_fn_test(CodeGen *g, ImportTableEntry *import, - BlockContext *context, AstNode *node) -{ - AstNode **fn_node = &node->data.fn_call_expr.params.at(0); - AstNode **value_node = &node->data.fn_call_expr.params.at(1); - - FnTableEntry *fn_entry = resolve_const_expr_fn(g, import, context, fn_node); - if (!fn_entry) { - return g->builtin_types.entry_invalid; - } - - bool ok = resolve_const_expr_bool(g, import, context, value_node, &fn_entry->is_test); - if (!ok) { - return g->builtin_types.entry_invalid; - } - - if (fn_entry->fn_test_set_node) { - ErrorMsg *msg = add_node_error(g, node, buf_sprintf("function test attribute set twice")); - add_error_note(g, msg, fn_entry->fn_test_set_node, buf_sprintf("first set here")); - return g->builtin_types.entry_invalid; - } - fn_entry->fn_test_set_node = node; - - g->test_fn_count += 1; - return g->builtin_types.entry_void; -} - -static TypeTableEntry *analyze_set_fn_no_inline(CodeGen *g, ImportTableEntry *import, - BlockContext *context, AstNode *node) -{ - AstNode **fn_node = &node->data.fn_call_expr.params.at(0); - AstNode **value_node = &node->data.fn_call_expr.params.at(1); - - FnTableEntry *fn_entry = resolve_const_expr_fn(g, import, context, fn_node); - if (!fn_entry) { - return g->builtin_types.entry_invalid; - } - - bool is_noinline; - bool ok = resolve_const_expr_bool(g, import, context, value_node, &is_noinline); - if (!ok) { - return g->builtin_types.entry_invalid; - } - - if (fn_entry->fn_no_inline_set_node) { - ErrorMsg *msg = add_node_error(g, node, buf_sprintf("function no inline attribute set twice")); - add_error_note(g, msg, fn_entry->fn_no_inline_set_node, buf_sprintf("first set here")); - return g->builtin_types.entry_invalid; - } - fn_entry->fn_no_inline_set_node = node; - - if (fn_entry->fn_inline == FnInlineAlways) { - add_node_error(g, node, buf_sprintf("function is both inline and noinline")); - fn_entry->proto_node->data.fn_proto.skip = true; - return g->builtin_types.entry_invalid; - } else if (is_noinline) { - fn_entry->fn_inline = FnInlineNever; - } - - return g->builtin_types.entry_void; -} - -static TypeTableEntry *analyze_set_fn_static_eval(CodeGen *g, ImportTableEntry *import, - BlockContext *context, AstNode *node) -{ - AstNode **fn_node = &node->data.fn_call_expr.params.at(0); - AstNode **value_node = &node->data.fn_call_expr.params.at(1); - - FnTableEntry *fn_entry = resolve_const_expr_fn(g, import, context, fn_node); - if (!fn_entry) { - return g->builtin_types.entry_invalid; - } - - bool want_static_eval; - bool ok = resolve_const_expr_bool(g, import, context, value_node, &want_static_eval); - if (!ok) { - return g->builtin_types.entry_invalid; - } - - if (fn_entry->fn_static_eval_set_node) { - ErrorMsg *msg = add_node_error(g, node, buf_sprintf("function static eval attribute set twice")); - add_error_note(g, msg, fn_entry->fn_static_eval_set_node, buf_sprintf("first set here")); - return g->builtin_types.entry_invalid; - } - fn_entry->fn_static_eval_set_node = node; - - if (want_static_eval && !context->fn_entry->is_pure) { - add_node_error(g, node, buf_sprintf("attribute appears too late within function")); - return g->builtin_types.entry_invalid; - } - - if (want_static_eval) { - fn_entry->want_pure = WantPureTrue; - fn_entry->want_pure_attr_node = node; - } else { - fn_entry->want_pure = WantPureFalse; - fn_entry->is_pure = false; - } - - return g->builtin_types.entry_void; -} - -static TypeTableEntry *analyze_set_fn_visible(CodeGen *g, ImportTableEntry *import, - BlockContext *context, AstNode *node) -{ - AstNode **fn_node = &node->data.fn_call_expr.params.at(0); - AstNode **value_node = &node->data.fn_call_expr.params.at(1); - - FnTableEntry *fn_entry = resolve_const_expr_fn(g, import, context, fn_node); - if (!fn_entry) { - return g->builtin_types.entry_invalid; - } - - bool want_export; - bool ok = resolve_const_expr_bool(g, import, context, value_node, &want_export); - if (!ok) { - return g->builtin_types.entry_invalid; - } - - if (fn_entry->fn_export_set_node) { - ErrorMsg *msg = add_node_error(g, node, buf_sprintf("function visibility set twice")); - add_error_note(g, msg, fn_entry->fn_export_set_node, buf_sprintf("first set here")); - return g->builtin_types.entry_invalid; - } - fn_entry->fn_export_set_node = node; - - AstNodeFnProto *fn_proto = &fn_entry->proto_node->data.fn_proto; - if (fn_proto->top_level_decl.visib_mod != VisibModExport) { - ErrorMsg *msg = add_node_error(g, node, - buf_sprintf("function must be marked export to set function visibility")); - add_error_note(g, msg, fn_entry->proto_node, buf_sprintf("function declared here")); - return g->builtin_types.entry_void; - } - if (!want_export) { - fn_proto->top_level_decl.visib_mod = VisibModPub; - } - - return g->builtin_types.entry_void; -} - -static TypeTableEntry *analyze_set_debug_safety(CodeGen *g, ImportTableEntry *import, - BlockContext *parent_context, AstNode *node) -{ - AstNode **target_node = &node->data.fn_call_expr.params.at(0); - AstNode **value_node = &node->data.fn_call_expr.params.at(1); - - TypeTableEntry *target_type = analyze_expression(g, import, parent_context, nullptr, *target_node); - BlockContext *target_context; - ConstExprValue *const_val = &get_resolved_expr(*target_node)->const_val; - if (target_type->id == TypeTableEntryIdInvalid) { - return g->builtin_types.entry_invalid; - } - if (!const_val->ok) { - add_node_error(g, *target_node, buf_sprintf("unable to evaluate constant expression")); - return g->builtin_types.entry_invalid; - } - if (target_type->id == TypeTableEntryIdBlock) { - target_context = const_val->data.x_block; - } else if (target_type->id == TypeTableEntryIdFn) { - target_context = const_val->data.x_fn->fn_def_node->data.fn_def.block_context; - } else if (target_type->id == TypeTableEntryIdMetaType) { - TypeTableEntry *type_arg = const_val->data.x_type; - if (type_arg->id == TypeTableEntryIdStruct) { - target_context = type_arg->data.structure.block_context; - } else if (type_arg->id == TypeTableEntryIdEnum) { - target_context = type_arg->data.enumeration.block_context; - } else if (type_arg->id == TypeTableEntryIdUnion) { - target_context = type_arg->data.unionation.block_context; - } else { - add_node_error(g, *target_node, - buf_sprintf("expected scope reference, got type '%s'", buf_ptr(&type_arg->name))); - return g->builtin_types.entry_invalid; - } - } else { - add_node_error(g, *target_node, - buf_sprintf("expected scope reference, got type '%s'", buf_ptr(&target_type->name))); - return g->builtin_types.entry_invalid; - } - - bool want_debug_safety; - bool ok = resolve_const_expr_bool(g, import, parent_context, value_node, &want_debug_safety); - if (!ok) { - return g->builtin_types.entry_invalid; - } - - if (target_context->safety_set_node) { - ErrorMsg *msg = add_node_error(g, node, buf_sprintf("debug safety for scope set twice")); - add_error_note(g, msg, target_context->safety_set_node, buf_sprintf("first set here")); - return g->builtin_types.entry_invalid; - } - target_context->safety_set_node = node; - - target_context->safety_off = !want_debug_safety; - - return g->builtin_types.entry_void; -} - -static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, - TypeTableEntry *expected_type, AstNode *node) -{ - assert(node->type == NodeTypeFnCallExpr); - - AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr; - Buf *name = fn_ref_expr->data.symbol_expr.symbol; - - auto entry = g->builtin_fn_table.maybe_get(name); - - if (!entry) { - add_node_error(g, node, - buf_sprintf("invalid builtin function: '%s'", buf_ptr(name))); - return g->builtin_types.entry_invalid; - } - - BuiltinFnEntry *builtin_fn = entry->value; - size_t actual_param_count = node->data.fn_call_expr.params.length; - - node->data.fn_call_expr.builtin_fn = builtin_fn; - - if (builtin_fn->param_count != actual_param_count) { - add_node_error(g, node, - buf_sprintf("expected %zu arguments, got %zu", - builtin_fn->param_count, actual_param_count)); - return g->builtin_types.entry_invalid; - } - - builtin_fn->ref_count += 1; - - switch (builtin_fn->id) { - case BuiltinFnIdInvalid: - zig_unreachable(); - case BuiltinFnIdAddWithOverflow: - case BuiltinFnIdSubWithOverflow: - case BuiltinFnIdMulWithOverflow: - case BuiltinFnIdShlWithOverflow: - { - AstNode *type_node = node->data.fn_call_expr.params.at(0); - TypeTableEntry *int_type = analyze_type_expr(g, import, context, type_node); - if (int_type->id == TypeTableEntryIdInvalid) { - return g->builtin_types.entry_bool; - } else if (int_type->id == TypeTableEntryIdInt) { - AstNode *op1_node = node->data.fn_call_expr.params.at(1); - AstNode *op2_node = node->data.fn_call_expr.params.at(2); - AstNode *result_node = node->data.fn_call_expr.params.at(3); - - analyze_expression(g, import, context, int_type, op1_node); - analyze_expression(g, import, context, int_type, op2_node); - analyze_expression(g, import, context, get_pointer_to_type(g, int_type, false), - result_node); - } else { - add_node_error(g, type_node, - buf_sprintf("expected integer type, got '%s'", buf_ptr(&int_type->name))); - } - - // TODO constant expression evaluation - - return g->builtin_types.entry_bool; - } - case BuiltinFnIdMemcpy: - { - AstNode *dest_node = node->data.fn_call_expr.params.at(0); - AstNode *src_node = node->data.fn_call_expr.params.at(1); - AstNode *len_node = node->data.fn_call_expr.params.at(2); - TypeTableEntry *dest_type = analyze_expression(g, import, context, nullptr, dest_node); - TypeTableEntry *src_type = analyze_expression(g, import, context, nullptr, src_node); - analyze_expression(g, import, context, builtin_fn->param_types[2], len_node); - - if (dest_type->id != TypeTableEntryIdInvalid && - dest_type->id != TypeTableEntryIdPointer) - { - add_node_error(g, dest_node, - buf_sprintf("expected pointer argument, got '%s'", buf_ptr(&dest_type->name))); - } - - if (src_type->id != TypeTableEntryIdInvalid && - src_type->id != TypeTableEntryIdPointer) - { - add_node_error(g, src_node, - buf_sprintf("expected pointer argument, got '%s'", buf_ptr(&src_type->name))); - } - - if (dest_type->id == TypeTableEntryIdPointer && - src_type->id == TypeTableEntryIdPointer) - { - uint64_t dest_align = get_memcpy_align(g, dest_type->data.pointer.child_type); - uint64_t src_align = get_memcpy_align(g, src_type->data.pointer.child_type); - if (dest_align != src_align) { - add_node_error(g, dest_node, buf_sprintf( - "misaligned memcpy, '%s' has alignment '%" PRIu64 ", '%s' has alignment %" PRIu64, - buf_ptr(&dest_type->name), dest_align, - buf_ptr(&src_type->name), src_align)); - } - } - - return builtin_fn->return_type; - } - case BuiltinFnIdMemset: - { - AstNode *dest_node = node->data.fn_call_expr.params.at(0); - AstNode *char_node = node->data.fn_call_expr.params.at(1); - AstNode *len_node = node->data.fn_call_expr.params.at(2); - TypeTableEntry *dest_type = analyze_expression(g, import, context, nullptr, dest_node); - analyze_expression(g, import, context, builtin_fn->param_types[1], char_node); - analyze_expression(g, import, context, builtin_fn->param_types[2], len_node); - - if (dest_type->id != TypeTableEntryIdInvalid && - dest_type->id != TypeTableEntryIdPointer) - { - add_node_error(g, dest_node, - buf_sprintf("expected pointer argument, got '%s'", buf_ptr(&dest_type->name))); - } - - return builtin_fn->return_type; - } - case BuiltinFnIdSizeof: - { - AstNode *type_node = node->data.fn_call_expr.params.at(0); - TypeTableEntry *type_entry = analyze_type_expr(g, import, context, type_node); - if (type_entry->id == TypeTableEntryIdInvalid) { - return g->builtin_types.entry_invalid; - } else if (type_entry->id == TypeTableEntryIdUnreachable) { - add_node_error(g, first_executing_node(type_node), - buf_sprintf("no size available for type '%s'", buf_ptr(&type_entry->name))); - return g->builtin_types.entry_invalid; - } else { - uint64_t size_in_bytes = type_size(g, type_entry); - bool depends_on_compile_var = (type_entry == g->builtin_types.entry_usize || - type_entry == g->builtin_types.entry_isize); - return resolve_expr_const_val_as_unsigned_num_lit(g, node, expected_type, - size_in_bytes, depends_on_compile_var); - } - } - case BuiltinFnIdAlignof: - { - AstNode *type_node = node->data.fn_call_expr.params.at(0); - TypeTableEntry *type_entry = analyze_type_expr(g, import, context, type_node); - if (type_entry->id == TypeTableEntryIdInvalid) { - return g->builtin_types.entry_invalid; - } else if (type_entry->id == TypeTableEntryIdUnreachable) { - add_node_error(g, first_executing_node(type_node), - buf_sprintf("no align available for type '%s'", buf_ptr(&type_entry->name))); - return g->builtin_types.entry_invalid; - } else { - uint64_t align_in_bytes = LLVMABISizeOfType(g->target_data_ref, type_entry->type_ref); - return resolve_expr_const_val_as_unsigned_num_lit(g, node, expected_type, - align_in_bytes, false); - } - } - case BuiltinFnIdMaxValue: - return analyze_min_max_value(g, import, context, node, - "no max value available for type '%s'", true); - case BuiltinFnIdMinValue: - return analyze_min_max_value(g, import, context, node, - "no min value available for type '%s'", false); - case BuiltinFnIdMemberCount: - { - AstNode *type_node = node->data.fn_call_expr.params.at(0); - TypeTableEntry *type_entry = analyze_type_expr(g, import, context, type_node); - - if (type_entry->id == TypeTableEntryIdInvalid) { - return type_entry; - } else if (type_entry->id == TypeTableEntryIdEnum) { - uint64_t value_count = type_entry->data.enumeration.src_field_count; - return resolve_expr_const_val_as_unsigned_num_lit(g, node, expected_type, - value_count, false); - } else { - add_node_error(g, node, - buf_sprintf("no value count available for type '%s'", buf_ptr(&type_entry->name))); - return g->builtin_types.entry_invalid; - } - } - case BuiltinFnIdTypeof: - { - AstNode *expr_node = node->data.fn_call_expr.params.at(0); - TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, expr_node); - - switch (type_entry->id) { - case TypeTableEntryIdInvalid: - return type_entry; - case TypeTableEntryIdNumLitFloat: - case TypeTableEntryIdNumLitInt: - case TypeTableEntryIdUndefLit: - case TypeTableEntryIdNullLit: - case TypeTableEntryIdNamespace: - case TypeTableEntryIdBlock: - case TypeTableEntryIdGenericFn: - case TypeTableEntryIdVar: - add_node_error(g, expr_node, - buf_sprintf("type '%s' not eligible for @typeOf", buf_ptr(&type_entry->name))); - return g->builtin_types.entry_invalid; - case TypeTableEntryIdMetaType: - case TypeTableEntryIdVoid: - case TypeTableEntryIdBool: - case TypeTableEntryIdUnreachable: - case TypeTableEntryIdInt: - case TypeTableEntryIdFloat: - case TypeTableEntryIdPointer: - case TypeTableEntryIdArray: - case TypeTableEntryIdStruct: - case TypeTableEntryIdMaybe: - case TypeTableEntryIdErrorUnion: - case TypeTableEntryIdPureError: - case TypeTableEntryIdEnum: - case TypeTableEntryIdUnion: - case TypeTableEntryIdFn: - case TypeTableEntryIdTypeDecl: - return resolve_expr_const_val_as_type(g, node, type_entry, false); - } - } - case BuiltinFnIdCInclude: - { - if (!context->c_import_buf) { - add_node_error(g, node, buf_sprintf("@c_include valid only in c_import blocks")); - return g->builtin_types.entry_invalid; - } - - AstNode **str_node = node->data.fn_call_expr.params.at(0)->parent_field; - TypeTableEntry *str_type = get_slice_type(g, g->builtin_types.entry_u8, true); - TypeTableEntry *resolved_type = analyze_expression(g, import, context, str_type, *str_node); - - if (resolved_type->id == TypeTableEntryIdInvalid) { - return resolved_type; - } - - ConstExprValue *const_str_val = &get_resolved_expr(*str_node)->const_val; - - if (!const_str_val->ok) { - add_node_error(g, *str_node, buf_sprintf("@c_include requires constant expression")); - return g->builtin_types.entry_void; - } - - buf_appendf(context->c_import_buf, "#include <"); - ConstExprValue *ptr_field = const_str_val->data.x_struct.fields[0]; - uint64_t len = ptr_field->data.x_ptr.len; - for (uint64_t i = 0; i < len; i += 1) { - ConstExprValue *char_val = ptr_field->data.x_ptr.ptr[i]; - uint64_t big_c = char_val->data.x_bignum.data.x_uint; - assert(big_c <= UINT8_MAX); - uint8_t c = big_c; - buf_append_char(context->c_import_buf, c); - } - buf_appendf(context->c_import_buf, ">\n"); - - return g->builtin_types.entry_void; - } - case BuiltinFnIdCDefine: - zig_panic("TODO"); - case BuiltinFnIdCUndef: - zig_panic("TODO"); - - case BuiltinFnIdCompileVar: - { - AstNode **str_node = node->data.fn_call_expr.params.at(0)->parent_field; - - Buf *var_name = resolve_const_expr_str(g, import, context, str_node); - if (!var_name) { - return g->builtin_types.entry_invalid; - } - - ConstExprValue *const_val = &get_resolved_expr(node)->const_val; - const_val->ok = true; - const_val->depends_on_compile_var = true; - - if (buf_eql_str(var_name, "is_big_endian")) { - return resolve_expr_const_val_as_bool(g, node, g->is_big_endian, true); - } else if (buf_eql_str(var_name, "is_release")) { - return resolve_expr_const_val_as_bool(g, node, g->is_release_build, true); - } else if (buf_eql_str(var_name, "is_test")) { - return resolve_expr_const_val_as_bool(g, node, g->is_test_build, true); - } else if (buf_eql_str(var_name, "os")) { - const_val->data.x_enum.tag = g->target_os_index; - return g->builtin_types.entry_os_enum; - } else if (buf_eql_str(var_name, "arch")) { - const_val->data.x_enum.tag = g->target_arch_index; - return g->builtin_types.entry_arch_enum; - } else if (buf_eql_str(var_name, "environ")) { - const_val->data.x_enum.tag = g->target_environ_index; - return g->builtin_types.entry_environ_enum; - } else if (buf_eql_str(var_name, "object_format")) { - const_val->data.x_enum.tag = g->target_oformat_index; - return g->builtin_types.entry_oformat_enum; - } else { - add_node_error(g, *str_node, - buf_sprintf("unrecognized compile variable: '%s'", buf_ptr(var_name))); - return g->builtin_types.entry_invalid; - } - } - case BuiltinFnIdConstEval: - { - AstNode **expr_node = node->data.fn_call_expr.params.at(0)->parent_field; - TypeTableEntry *resolved_type = analyze_expression(g, import, context, expected_type, *expr_node); - if (resolved_type->id == TypeTableEntryIdInvalid) { - return resolved_type; - } - - ConstExprValue *const_expr_val = &get_resolved_expr(*expr_node)->const_val; - - if (!const_expr_val->ok) { - add_node_error(g, *expr_node, buf_sprintf("unable to evaluate constant expression")); - return g->builtin_types.entry_invalid; - } - - ConstExprValue *const_val = &get_resolved_expr(node)->const_val; - *const_val = *const_expr_val; - - return resolved_type; - } - case BuiltinFnIdCtz: - case BuiltinFnIdClz: - { - AstNode *type_node = node->data.fn_call_expr.params.at(0); - TypeTableEntry *int_type = analyze_type_expr(g, import, context, type_node); - if (int_type->id == TypeTableEntryIdInvalid) { - return int_type; - } else if (int_type->id == TypeTableEntryIdInt) { - AstNode **expr_node = node->data.fn_call_expr.params.at(1)->parent_field; - TypeTableEntry *resolved_type = analyze_expression(g, import, context, int_type, *expr_node); - if (resolved_type->id == TypeTableEntryIdInvalid) { - return resolved_type; - } - - // TODO const expr eval - - return resolved_type; - } else { - add_node_error(g, type_node, - buf_sprintf("expected integer type, got '%s'", buf_ptr(&int_type->name))); - return g->builtin_types.entry_invalid; - } - } - case BuiltinFnIdImport: - return analyze_import(g, import, context, node); - case BuiltinFnIdCImport: - return analyze_c_import(g, import, context, node); - case BuiltinFnIdErrName: - return analyze_err_name(g, import, context, node); - case BuiltinFnIdBreakpoint: - mark_impure_fn(g, context, node); - return g->builtin_types.entry_void; - case BuiltinFnIdReturnAddress: - case BuiltinFnIdFrameAddress: - mark_impure_fn(g, context, node); - return builtin_fn->return_type; - case BuiltinFnIdEmbedFile: - return analyze_embed_file(g, import, context, node); - case BuiltinFnIdCmpExchange: - return analyze_cmpxchg(g, import, context, node); - case BuiltinFnIdFence: - return analyze_fence(g, import, context, node); - case BuiltinFnIdDivExact: - return analyze_div_exact(g, import, context, node); - case BuiltinFnIdTruncate: - return analyze_truncate(g, import, context, node); - case BuiltinFnIdCompileErr: - return analyze_compile_err(g, import, context, node); - case BuiltinFnIdIntType: - return analyze_int_type(g, import, context, node); - case BuiltinFnIdUnreachable: - return g->builtin_types.entry_unreachable; - case BuiltinFnIdSetFnTest: - return analyze_set_fn_test(g, import, context, node); - case BuiltinFnIdSetFnNoInline: - return analyze_set_fn_no_inline(g, import, context, node); - case BuiltinFnIdSetFnStaticEval: - return analyze_set_fn_static_eval(g, import, context, node); - case BuiltinFnIdSetFnVisible: - return analyze_set_fn_visible(g, import, context, node); - case BuiltinFnIdSetDebugSafety: - return analyze_set_debug_safety(g, import, context, node); - } - zig_unreachable(); -} - static TypeTableEntry *bad_method_call(CodeGen *g, AstNode *node, TypeTableEntry *container_type, TypeTableEntry *expected_param_type, FnTableEntry *fn_table_entry) { @@ -5817,7 +4730,7 @@ static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr; if (node->data.fn_call_expr.is_builtin) { - return analyze_builtin_fn_call_expr(g, import, context, expected_type, node); + zig_panic("moved builtin fn call code to ir.cpp"); } TypeTableEntry *invoke_type_entry = analyze_expression(g, import, context, nullptr, fn_ref_expr); @@ -5885,222 +4798,6 @@ static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import } } -static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, - TypeTableEntry *expected_type, AstNode *node) -{ - PrefixOp prefix_op = node->data.prefix_op_expr.prefix_op; - AstNode **expr_node = &node->data.prefix_op_expr.primary_expr; - switch (prefix_op) { - case PrefixOpInvalid: - zig_unreachable(); - case PrefixOpBoolNot: - { - TypeTableEntry *type_entry = analyze_expression(g, import, context, g->builtin_types.entry_bool, - *expr_node); - if (type_entry->id == TypeTableEntryIdInvalid) { - return g->builtin_types.entry_bool; - } - - ConstExprValue *target_const_val = &get_resolved_expr(*expr_node)->const_val; - if (!target_const_val->ok) { - return g->builtin_types.entry_bool; - } - - bool answer = !target_const_val->data.x_bool; - return resolve_expr_const_val_as_bool(g, node, answer, target_const_val->depends_on_compile_var); - } - case PrefixOpBinNot: - { - TypeTableEntry *expr_type = analyze_expression(g, import, context, expected_type, - *expr_node); - if (expr_type->id == TypeTableEntryIdInvalid) { - return expr_type; - } else if (expr_type->id == TypeTableEntryIdInt) { - return expr_type; - } else { - add_node_error(g, node, buf_sprintf("unable to perform binary not operation on type '%s'", - buf_ptr(&expr_type->name))); - return g->builtin_types.entry_invalid; - } - // TODO const expr eval - } - case PrefixOpNegation: - case PrefixOpNegationWrap: - { - TypeTableEntry *expr_type = analyze_expression(g, import, context, nullptr, *expr_node); - if (expr_type->id == TypeTableEntryIdInvalid) { - return expr_type; - } else if ((expr_type->id == TypeTableEntryIdInt && - expr_type->data.integral.is_signed) || - expr_type->id == TypeTableEntryIdNumLitInt || - ((expr_type->id == TypeTableEntryIdFloat || - expr_type->id == TypeTableEntryIdNumLitFloat) && - prefix_op != PrefixOpNegationWrap)) - { - ConstExprValue *target_const_val = &get_resolved_expr(*expr_node)->const_val; - if (!target_const_val->ok) { - return expr_type; - } - ConstExprValue *const_val = &get_resolved_expr(node)->const_val; - const_val->ok = true; - const_val->depends_on_compile_var = target_const_val->depends_on_compile_var; - bignum_negate(&const_val->data.x_bignum, &target_const_val->data.x_bignum); - if (expr_type->id == TypeTableEntryIdFloat || - expr_type->id == TypeTableEntryIdNumLitFloat || - expr_type->id == TypeTableEntryIdNumLitInt) - { - return expr_type; - } - - bool overflow = !bignum_fits_in_bits(&const_val->data.x_bignum, - expr_type->data.integral.bit_count, expr_type->data.integral.is_signed); - if (prefix_op == PrefixOpNegationWrap) { - if (overflow) { - const_val->data.x_bignum.is_negative = true; - } - } else if (overflow) { - add_node_error(g, *expr_node, buf_sprintf("negation caused overflow")); - return g->builtin_types.entry_invalid; - } - return expr_type; - } else { - const char *fmt = (prefix_op == PrefixOpNegationWrap) ? - "invalid wrapping negation type: '%s'" : "invalid negation type: '%s'"; - add_node_error(g, node, buf_sprintf(fmt, buf_ptr(&expr_type->name))); - return g->builtin_types.entry_invalid; - } - } - case PrefixOpAddressOf: - case PrefixOpConstAddressOf: - { - bool is_const = (prefix_op == PrefixOpConstAddressOf); - - TypeTableEntry *child_type = analyze_lvalue(g, import, context, - *expr_node, LValPurposeAddressOf, is_const); - - if (child_type->id == TypeTableEntryIdInvalid) { - return g->builtin_types.entry_invalid; - } else if (child_type->id == TypeTableEntryIdMetaType) { - TypeTableEntry *meta_type = analyze_type_expr_pointer_only(g, import, context, - *expr_node, true); - if (meta_type->id == TypeTableEntryIdInvalid) { - return g->builtin_types.entry_invalid; - } else if (meta_type->id == TypeTableEntryIdUnreachable) { - add_node_error(g, node, buf_create_from_str("pointer to unreachable not allowed")); - return g->builtin_types.entry_invalid; - } else { - return resolve_expr_const_val_as_type(g, node, - get_pointer_to_type(g, meta_type, is_const), false); - } - } else if (child_type->id == TypeTableEntryIdNumLitInt || - child_type->id == TypeTableEntryIdNumLitFloat) - { - add_node_error(g, *expr_node, - buf_sprintf("unable to get address of type '%s'", buf_ptr(&child_type->name))); - return g->builtin_types.entry_invalid; - } else { - return get_pointer_to_type(g, child_type, is_const); - } - } - case PrefixOpDereference: - { - TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, *expr_node); - if (type_entry->id == TypeTableEntryIdInvalid) { - return type_entry; - } else if (type_entry->id == TypeTableEntryIdPointer) { - return type_entry->data.pointer.child_type; - } else { - add_node_error(g, *expr_node, - buf_sprintf("indirection requires pointer operand ('%s' invalid)", - buf_ptr(&type_entry->name))); - return g->builtin_types.entry_invalid; - } - } - case PrefixOpMaybe: - { - TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, *expr_node); - - if (type_entry->id == TypeTableEntryIdInvalid) { - return type_entry; - } else if (type_entry->id == TypeTableEntryIdMetaType) { - TypeTableEntry *meta_type = resolve_type(g, *expr_node); - if (meta_type->id == TypeTableEntryIdInvalid) { - return g->builtin_types.entry_invalid; - } else if (meta_type->id == TypeTableEntryIdUnreachable) { - add_node_error(g, node, buf_create_from_str("unable to wrap unreachable in maybe type")); - return g->builtin_types.entry_invalid; - } else { - return resolve_expr_const_val_as_type(g, node, get_maybe_type(g, meta_type), false); - } - } else if (type_entry->id == TypeTableEntryIdUnreachable) { - add_node_error(g, *expr_node, buf_sprintf("unable to wrap unreachable in maybe type")); - return g->builtin_types.entry_invalid; - } else { - ConstExprValue *target_const_val = &get_resolved_expr(*expr_node)->const_val; - TypeTableEntry *maybe_type = get_maybe_type(g, type_entry); - if (!target_const_val->ok) { - return maybe_type; - } - return resolve_expr_const_val_as_non_null(g, node, maybe_type, target_const_val); - } - } - case PrefixOpError: - { - TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, *expr_node); - - if (type_entry->id == TypeTableEntryIdInvalid) { - return type_entry; - } else if (type_entry->id == TypeTableEntryIdMetaType) { - TypeTableEntry *meta_type = resolve_type(g, *expr_node); - if (meta_type->id == TypeTableEntryIdInvalid) { - return meta_type; - } else if (meta_type->id == TypeTableEntryIdUnreachable) { - add_node_error(g, node, buf_create_from_str("unable to wrap unreachable in error type")); - return g->builtin_types.entry_invalid; - } else { - return resolve_expr_const_val_as_type(g, node, get_error_type(g, meta_type), false); - } - } else if (type_entry->id == TypeTableEntryIdUnreachable) { - add_node_error(g, *expr_node, buf_sprintf("unable to wrap unreachable in error type")); - return g->builtin_types.entry_invalid; - } else { - // TODO eval const expr - return get_error_type(g, type_entry); - } - - } - case PrefixOpUnwrapError: - { - TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, *expr_node); - - if (type_entry->id == TypeTableEntryIdInvalid) { - return type_entry; - } else if (type_entry->id == TypeTableEntryIdErrorUnion) { - return type_entry->data.error.child_type; - } else { - add_node_error(g, *expr_node, - buf_sprintf("expected error type, got '%s'", buf_ptr(&type_entry->name))); - return g->builtin_types.entry_invalid; - } - } - case PrefixOpUnwrapMaybe: - { - TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, *expr_node); - - if (type_entry->id == TypeTableEntryIdInvalid) { - return type_entry; - } else if (type_entry->id == TypeTableEntryIdMaybe) { - return type_entry->data.maybe.child_type; - } else { - add_node_error(g, *expr_node, - buf_sprintf("expected maybe type, got '%s'", buf_ptr(&type_entry->name))); - return g->builtin_types.entry_invalid; - } - } - } - zig_unreachable(); -} - static TypeTableEntry *analyze_switch_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, TypeTableEntry *expected_type, AstNode *node) { @@ -6665,7 +5362,7 @@ static TypeTableEntry *analyze_expression_pointer_only(CodeGen *g, ImportTableEn return_type = analyze_symbol_expr(g, import, context, expected_type, node, pointer_only); break; case NodeTypePrefixOpExpr: - return_type = analyze_prefix_op_expr(g, import, context, expected_type, node); + zig_panic("moved to ir.cpp"); break; case NodeTypeIfBoolExpr: return_type = analyze_if_bool_expr(g, import, context, expected_type, node); |
