aboutsummaryrefslogtreecommitdiff
path: root/src/analyze.cpp
diff options
context:
space:
mode:
authorAndrew Kelley <superjoe30@gmail.com>2016-10-11 23:45:33 -0400
committerAndrew Kelley <superjoe30@gmail.com>2016-10-11 23:45:33 -0400
commitce3c52471dd8a86e429ea037f4344b243723eb74 (patch)
treeb2e430b77c83b2141758adaed7484ff7a723b293 /src/analyze.cpp
parent77ae3442ef2dee1659ab5778f43c00026fd21dd9 (diff)
downloadzig-ce3c52471dd8a86e429ea037f4344b243723eb74.tar.gz
zig-ce3c52471dd8a86e429ea037f4344b243723eb74.zip
IR if statements WIP
Diffstat (limited to 'src/analyze.cpp')
-rw-r--r--src/analyze.cpp1307
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);