authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-10-11 23:45:33-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-10-11 23:45:33-04:00
logce3c52471dd8a86e429ea037f4344b243723eb74
treeb2e430b77c83b2141758adaed7484ff7a723b293
parent77ae3442ef2dee1659ab5778f43c00026fd21dd9

IR if statements WIP


5 files changed, 1756 insertions(+), 1505 deletions(-)

src/all_types.hpp+39-6
...@@ -1409,13 +1409,17 @@ enum AtomicOrder {...@@ -1409,13 +1409,17 @@ enum AtomicOrder {
1409struct IrBasicBlock {1409struct IrBasicBlock {
1410 ZigList<IrInstruction *> instruction_list;1410 ZigList<IrInstruction *> instruction_list;
1411 IrBasicBlock *other;1411 IrBasicBlock *other;
1412 const char *name_hint;
1413 size_t debug_id;
1412};1414};
14131415
1414enum IrInstructionId {1416enum IrInstructionId {
1415 IrInstructionIdInvalid,1417 IrInstructionIdInvalid,
1418 IrInstructionIdBr,
1416 IrInstructionIdCondBr,1419 IrInstructionIdCondBr,
1417 IrInstructionIdSwitchBr,1420 IrInstructionIdSwitchBr,
1418 IrInstructionIdPhi,1421 IrInstructionIdPhi,
1422 IrInstructionIdUnOp,
1419 IrInstructionIdBinOp,1423 IrInstructionIdBinOp,
1420 IrInstructionIdLoadVar,1424 IrInstructionIdLoadVar,
1421 IrInstructionIdStoreVar,1425 IrInstructionIdStoreVar,
...@@ -1442,9 +1446,15 @@ struct IrInstruction {...@@ -1442,9 +1446,15 @@ struct IrInstruction {
1442struct IrInstructionCondBr {1446struct IrInstructionCondBr {
1443 IrInstruction base;1447 IrInstruction base;
14441448
1445 // If cond_inst_index == SIZE_MAX, then this is an unconditional branch.1449 IrInstruction *condition;
1446 size_t cond_inst_index;1450 IrBasicBlock *then_block;
1447 size_t dest_basic_block_index;1451 IrBasicBlock *else_block;
1452};
1453
1454struct IrInstructionBr {
1455 IrInstruction base;
1456
1457 IrBasicBlock *dest_block;
1448};1458};
14491459
1450struct IrInstructionSwitchBrCase {1460struct IrInstructionSwitchBrCase {
...@@ -1464,11 +1474,35 @@ struct IrInstructionSwitchBr {...@@ -1464,11 +1474,35 @@ struct IrInstructionSwitchBr {
1464struct IrInstructionPhi {1474struct IrInstructionPhi {
1465 IrInstruction base;1475 IrInstruction base;
14661476
1467 size_t incoming_block_count;1477 size_t incoming_count;
1468 IrBasicBlock **incoming_blocks;1478 IrBasicBlock **incoming_blocks;
1469 IrInstruction **incoming_values;1479 IrInstruction **incoming_values;
1470};1480};
14711481
1482enum IrUnOp {
1483 IrUnOpInvalid,
1484 IrUnOpBoolNot,
1485 IrUnOpBinNot,
1486 IrUnOpNegation,
1487 IrUnOpNegationWrap,
1488 IrUnOpAddressOf,
1489 IrUnOpConstAddressOf,
1490 IrUnOpDereference,
1491 IrUnOpError,
1492 IrUnOpMaybe,
1493 IrUnOpUnwrapError,
1494 IrUnOpUnwrapMaybe,
1495 IrUnOpErrorReturn,
1496 IrUnOpMaybeReturn,
1497};
1498
1499struct IrInstructionUnOp {
1500 IrInstruction base;
1501
1502 IrUnOp op_id;
1503 IrInstruction *value;
1504};
1505
1472enum IrBinOp {1506enum IrBinOp {
1473 IrBinOpInvalid,1507 IrBinOpInvalid,
1474 IrBinOpBoolOr,1508 IrBinOpBoolOr,
...@@ -1529,8 +1563,7 @@ struct IrInstructionCall {...@@ -1529,8 +1563,7 @@ struct IrInstructionCall {
1529struct IrInstructionBuiltinCall {1563struct IrInstructionBuiltinCall {
1530 IrInstruction base;1564 IrInstruction base;
15311565
1532 BuiltinFnId fn_id;1566 BuiltinFnEntry *fn;
1533 size_t arg_count;
1534 IrInstruction **args;1567 IrInstruction **args;
1535};1568};
15361569
src/analyze.cpp+158-1461
...@@ -1067,76 +1067,6 @@ static TypeTableEntry *analyze_fn_proto_type(CodeGen *g, ImportTableEntry *impor...@@ -1067,76 +1067,6 @@ static TypeTableEntry *analyze_fn_proto_type(CodeGen *g, ImportTableEntry *impor
1067 return get_fn_type(g, &fn_type_id, gen_debug_info);1067 return get_fn_type(g, &fn_type_id, gen_debug_info);
1068}1068}
10691069
1070static Buf *resolve_const_expr_str(CodeGen *g, ImportTableEntry *import, BlockContext *context, AstNode **node) {
1071 TypeTableEntry *str_type = get_slice_type(g, g->builtin_types.entry_u8, true);
1072 TypeTableEntry *resolved_type = analyze_expression(g, import, context, str_type, *node);
1073
1074 if (resolved_type->id == TypeTableEntryIdInvalid) {
1075 return nullptr;
1076 }
1077
1078 ConstExprValue *const_str_val = &get_resolved_expr(*node)->const_val;
1079
1080 if (!const_str_val->ok) {
1081 add_node_error(g, *node, buf_sprintf("unable to evaluate constant expression"));
1082 return nullptr;
1083 }
1084
1085 ConstExprValue *ptr_field = const_str_val->data.x_struct.fields[0];
1086 uint64_t len = ptr_field->data.x_ptr.len;
1087 Buf *result = buf_alloc();
1088 for (uint64_t i = 0; i < len; i += 1) {
1089 ConstExprValue *char_val = ptr_field->data.x_ptr.ptr[i];
1090 uint64_t big_c = char_val->data.x_bignum.data.x_uint;
1091 assert(big_c <= UINT8_MAX);
1092 uint8_t c = big_c;
1093 buf_append_char(result, c);
1094 }
1095 return result;
1096}
1097
1098static bool resolve_const_expr_bool(CodeGen *g, ImportTableEntry *import, BlockContext *context,
1099 AstNode **node, bool *value)
1100{
1101 TypeTableEntry *resolved_type = analyze_expression(g, import, context, g->builtin_types.entry_bool, *node);
1102
1103 if (resolved_type->id == TypeTableEntryIdInvalid) {
1104 return false;
1105 }
1106
1107 ConstExprValue *const_bool_val = &get_resolved_expr(*node)->const_val;
1108
1109 if (!const_bool_val->ok) {
1110 add_node_error(g, *node, buf_sprintf("unable to evaluate constant expression"));
1111 return false;
1112 }
1113
1114 *value = const_bool_val->data.x_bool;
1115 return true;
1116}
1117
1118static FnTableEntry *resolve_const_expr_fn(CodeGen *g, ImportTableEntry *import, BlockContext *context,
1119 AstNode **node)
1120{
1121 TypeTableEntry *resolved_type = analyze_expression(g, import, context, nullptr, *node);
1122
1123 if (resolved_type->id == TypeTableEntryIdInvalid) {
1124 return nullptr;
1125 } else if (resolved_type->id == TypeTableEntryIdFn) {
1126 ConstExprValue *const_val = &get_resolved_expr(*node)->const_val;
1127
1128 if (!const_val->ok) {
1129 add_node_error(g, *node, buf_sprintf("unable to evaluate constant expression"));
1130 return nullptr;
1131 }
1132
1133 return const_val->data.x_fn;
1134 } else {
1135 add_node_error(g, *node, buf_sprintf("expected function, got '%s'", buf_ptr(&resolved_type->name)));
1136 return nullptr;
1137 }
1138}
1139
1140static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_table_entry,1070static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_table_entry,
1141 ImportTableEntry *import, BlockContext *containing_context)1071 ImportTableEntry *import, BlockContext *containing_context)
1142{1072{
...@@ -3073,16 +3003,6 @@ static TypeTableEntry *resolve_expr_const_val_as_bool(CodeGen *g, AstNode *node,...@@ -3073,16 +3003,6 @@ static TypeTableEntry *resolve_expr_const_val_as_bool(CodeGen *g, AstNode *node,
3073 return g->builtin_types.entry_bool;3003 return g->builtin_types.entry_bool;
3074}3004}
30753005
3076static TypeTableEntry *resolve_expr_const_val_as_non_null(CodeGen *g, AstNode *node,
3077 TypeTableEntry *type, ConstExprValue *other_val)
3078{
3079 assert(other_val->ok);
3080 Expr *expr = get_resolved_expr(node);
3081 expr->const_val.ok = true;
3082 expr->const_val.data.x_maybe = other_val;
3083 return type;
3084}
3085
3086static TypeTableEntry *resolve_expr_const_val_as_c_string_lit(CodeGen *g, AstNode *node, Buf *str) {3006static TypeTableEntry *resolve_expr_const_val_as_c_string_lit(CodeGen *g, AstNode *node, Buf *str) {
3087 Expr *expr = get_resolved_expr(node);3007 Expr *expr = get_resolved_expr(node);
3088 expr->const_val.ok = true;3008 expr->const_val.ok = true;
...@@ -4432,33 +4352,6 @@ static TypeTableEntry *analyze_if_var_expr(CodeGen *g, ImportTableEntry *import,...@@ -4432,33 +4352,6 @@ static TypeTableEntry *analyze_if_var_expr(CodeGen *g, ImportTableEntry *import,
4432 node, then_node, else_node, cond_is_const, cond_bool_val);4352 node, then_node, else_node, cond_is_const, cond_bool_val);
4433}4353}
44344354
4435static TypeTableEntry *analyze_min_max_value(CodeGen *g, ImportTableEntry *import, BlockContext *context,
4436 AstNode *node, const char *err_format, bool is_max)
4437{
4438 assert(node->type == NodeTypeFnCallExpr);
4439 assert(node->data.fn_call_expr.params.length == 1);
4440
4441 AstNode *type_node = node->data.fn_call_expr.params.at(0);
4442 TypeTableEntry *type_entry = analyze_type_expr(g, import, context, type_node);
4443
4444 if (type_entry->id == TypeTableEntryIdInvalid) {
4445 return g->builtin_types.entry_invalid;
4446 } else if (type_entry->id == TypeTableEntryIdInt) {
4447 eval_min_max_value(g, type_entry, &get_resolved_expr(node)->const_val, is_max);
4448 return g->builtin_types.entry_num_lit_int;
4449 } else if (type_entry->id == TypeTableEntryIdFloat) {
4450 eval_min_max_value(g, type_entry, &get_resolved_expr(node)->const_val, is_max);
4451 return g->builtin_types.entry_num_lit_float;
4452 } else if (type_entry->id == TypeTableEntryIdBool) {
4453 eval_min_max_value(g, type_entry, &get_resolved_expr(node)->const_val, is_max);
4454 return type_entry;
4455 } else {
4456 add_node_error(g, node,
4457 buf_sprintf(err_format, buf_ptr(&type_entry->name)));
4458 return g->builtin_types.entry_invalid;
4459 }
4460}
4461
4462bool type_is_codegen_pointer(TypeTableEntry *type) {4355bool type_is_codegen_pointer(TypeTableEntry *type) {
4463 if (type->id == TypeTableEntryIdPointer) return true;4356 if (type->id == TypeTableEntryIdPointer) return true;
4464 if (type->id == TypeTableEntryIdFn) return true;4357 if (type->id == TypeTableEntryIdFn) return true;
...@@ -4469,1185 +4362,205 @@ bool type_is_codegen_pointer(TypeTableEntry *type) {...@@ -4469,1185 +4362,205 @@ bool type_is_codegen_pointer(TypeTableEntry *type) {
4469 return false;4362 return false;
4470}4363}
44714364
4472static TypeTableEntry *analyze_import(CodeGen *g, ImportTableEntry *import, BlockContext *context,4365static TypeTableEntry *bad_method_call(CodeGen *g, AstNode *node, TypeTableEntry *container_type,
4473 AstNode *node)4366 TypeTableEntry *expected_param_type, FnTableEntry *fn_table_entry)
4474{4367{
4475 assert(node->type == NodeTypeFnCallExpr);4368 ErrorMsg *msg = add_node_error(g, node,
44764369 buf_sprintf("function called as method of '%s', but first parameter is of type '%s'",
4477 if (context->fn_entry) {4370 buf_ptr(&container_type->name),
4478 add_node_error(g, node, buf_sprintf("@import invalid inside function bodies"));4371 buf_ptr(&expected_param_type->name)));
4479 return g->builtin_types.entry_invalid;4372 if (fn_table_entry) {
4373 add_error_note(g, msg, fn_table_entry->proto_node, buf_sprintf("function declared here"));
4480 }4374 }
4375 return g->builtin_types.entry_invalid;
4376}
44814377
4482 AstNode *first_param_node = node->data.fn_call_expr.params.at(0);4378// Before calling this function, set node->data.fn_call_expr.fn_table_entry if the function is known
4483 Buf *import_target_str = resolve_const_expr_str(g, import, context, first_param_node->parent_field);4379// at compile time. Otherwise this is a function pointer call.
4484 if (!import_target_str) {4380static TypeTableEntry *analyze_fn_call_ptr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
4485 return g->builtin_types.entry_invalid;4381 TypeTableEntry *expected_type, AstNode *node, TypeTableEntry *fn_type,
4486 }4382 AstNode *struct_node)
4383{
4384 assert(node->type == NodeTypeFnCallExpr);
44874385
4488 Buf *import_target_path;4386 if (fn_type->id == TypeTableEntryIdInvalid) {
4489 Buf *search_dir;4387 return fn_type;
4490 assert(import->package);
4491 PackageTableEntry *target_package;
4492 auto package_entry = import->package->package_table.maybe_get(import_target_str);
4493 if (package_entry) {
4494 target_package = package_entry->value;
4495 import_target_path = &target_package->root_src_path;
4496 search_dir = &target_package->root_src_dir;
4497 } else {
4498 // try it as a filename
4499 target_package = import->package;
4500 import_target_path = import_target_str;
4501 search_dir = &import->package->root_src_dir;
4502 }4388 }
45034389
4504 Buf full_path = BUF_INIT;4390 // The function call might include inline parameters which we need to ignore according to the
4505 os_path_join(search_dir, import_target_path, &full_path);4391 // fn_type.
4392 FnTableEntry *fn_table_entry = node->data.fn_call_expr.fn_entry;
4393 AstNode *generic_proto_node = fn_table_entry ?
4394 fn_table_entry->proto_node->data.fn_proto.generic_proto_node : nullptr;
45064395
4507 Buf *import_code = buf_alloc();4396 // count parameters
4508 Buf *abs_full_path = buf_alloc();4397 size_t struct_node_1_or_0 = struct_node ? 1 : 0;
4509 int err;4398 size_t src_param_count = fn_type->data.fn.fn_type_id.param_count +
4510 if ((err = os_path_real(&full_path, abs_full_path))) {4399 (generic_proto_node ? generic_proto_node->data.fn_proto.inline_arg_count : 0);
4511 if (err == ErrorFileNotFound) {4400 size_t call_param_count = node->data.fn_call_expr.params.length;
4512 add_node_error(g, node,4401 size_t expect_arg_count = src_param_count - struct_node_1_or_0;
4513 buf_sprintf("unable to find '%s'", buf_ptr(import_target_path)));
4514 return g->builtin_types.entry_invalid;
4515 } else {
4516 g->error_during_imports = true;
4517 add_node_error(g, node,
4518 buf_sprintf("unable to open '%s': %s", buf_ptr(&full_path), err_str(err)));
4519 return g->builtin_types.entry_invalid;
4520 }
4521 }
45224402
4523 auto import_entry = g->import_table.maybe_get(abs_full_path);4403 bool ok_invocation = true;
4524 if (import_entry) {
4525 return resolve_expr_const_val_as_import(g, node, import_entry->value);
4526 }
45274404
4528 if ((err = os_fetch_file_path(abs_full_path, import_code))) {4405 if (fn_type->data.fn.fn_type_id.is_var_args) {
4529 if (err == ErrorFileNotFound) {4406 if (call_param_count < expect_arg_count) {
4530 add_node_error(g, node,4407 ok_invocation = false;
4531 buf_sprintf("unable to find '%s'", buf_ptr(import_target_path)));
4532 return g->builtin_types.entry_invalid;
4533 } else {
4534 add_node_error(g, node,4408 add_node_error(g, node,
4535 buf_sprintf("unable to open '%s': %s", buf_ptr(&full_path), err_str(err)));4409 buf_sprintf("expected at least %zu arguments, got %zu", src_param_count, call_param_count));
4536 return g->builtin_types.entry_invalid;
4537 }4410 }
4411 } else if (expect_arg_count != call_param_count) {
4412 ok_invocation = false;
4413 add_node_error(g, node,
4414 buf_sprintf("expected %zu arguments, got %zu", expect_arg_count, call_param_count));
4538 }4415 }
4539 ImportTableEntry *target_import = add_source_file(g, target_package,
4540 abs_full_path, search_dir, import_target_path, import_code);
4541
4542 scan_decls(g, target_import, target_import->block_context, target_import->root);
45434416
4544 return resolve_expr_const_val_as_import(g, node, target_import);4417 bool all_args_const_expr = true;
4545}
45464418
4547static TypeTableEntry *analyze_c_import(CodeGen *g, ImportTableEntry *parent_import,4419 if (struct_node) {
4548 BlockContext *parent_context, AstNode *node)4420 Expr *struct_expr = get_resolved_expr(struct_node);
4549{4421 ConstExprValue *struct_const_val = &struct_expr->const_val;
4550 assert(node->type == NodeTypeFnCallExpr);4422 if (!struct_const_val->ok) {
4423 all_args_const_expr = false;
4424 }
45514425
4552 if (parent_context->fn_entry) {4426 FnTypeParamInfo *param_info = &fn_type->data.fn.fn_type_id.param_info[0];
4553 add_node_error(g, node, buf_sprintf("@c_import invalid inside function bodies"));4427 TypeTableEntry *expected_param_type = param_info->type;
4554 return g->builtin_types.entry_invalid;4428 TypeTableEntry *container_bare_type = container_ref_type(struct_expr->type_entry);
4429 if (is_container_ref(expected_param_type)) {
4430 TypeTableEntry *param_bare_type = container_ref_type(expected_param_type);
4431 if (param_bare_type != container_bare_type) {
4432 return bad_method_call(g, node, container_bare_type, expected_param_type, fn_table_entry);
4433 }
4434 } else {
4435 return bad_method_call(g, node, container_bare_type, expected_param_type, fn_table_entry);
4436 }
4555 }4437 }
45564438
4557 AstNode *block_node = node->data.fn_call_expr.params.at(0);4439 // analyze each parameter. in the case of a method, we already analyzed the
4440 // first parameter in order to figure out which struct we were calling a method on.
4441 size_t next_type_i = struct_node_1_or_0;
4442 for (size_t call_i = 0; call_i < call_param_count; call_i += 1) {
4443 size_t proto_i = call_i + struct_node_1_or_0;
4444 AstNode **param_node = &node->data.fn_call_expr.params.at(call_i);
4445 // determine the expected type for each parameter
4446 TypeTableEntry *expected_param_type = nullptr;
4447 if (proto_i < src_param_count) {
4448 if (generic_proto_node &&
4449 generic_proto_node->data.fn_proto.params.at(proto_i)->data.param_decl.is_inline)
4450 {
4451 continue;
4452 }
45584453
4559 BlockContext *child_context = new_block_context(node, parent_context);4454 FnTypeParamInfo *param_info = &fn_type->data.fn.fn_type_id.param_info[next_type_i];
4560 child_context->c_import_buf = buf_alloc();4455 next_type_i += 1;
45614456
4562 TypeTableEntry *resolved_type = analyze_expression(g, parent_import, child_context,4457 expected_param_type = param_info->type;
4563 g->builtin_types.entry_void, block_node);4458 }
4459 TypeTableEntry *param_type = analyze_expression(g, import, context, expected_param_type, *param_node);
4460 if (param_type->id == TypeTableEntryIdInvalid) {
4461 return param_type;
4462 }
45644463
4565 if (resolved_type->id == TypeTableEntryIdInvalid) {4464 ConstExprValue *const_arg_val = &get_resolved_expr(*param_node)->const_val;
4566 return resolved_type;4465 if (!const_arg_val->ok) {
4466 all_args_const_expr = false;
4467 }
4567 }4468 }
45684469
4569 find_libc_include_path(g);4470 TypeTableEntry *return_type = fn_type->data.fn.fn_type_id.return_type;
4570
4571 ImportTableEntry *child_import = allocate<ImportTableEntry>(1);
4572 child_import->c_import_node = node;
4573
4574 ZigList<ErrorMsg *> errors = {0};
45754471
4576 int err;4472 if (return_type->id == TypeTableEntryIdInvalid) {
4577 if ((err = parse_h_buf(child_import, &errors, child_context->c_import_buf, g, node))) {4473 return return_type;
4578 zig_panic("unable to parse h file: %s\n", err_str(err));
4579 }4474 }
45804475
4581 if (errors.length > 0) {4476 ConstExprValue *result_val = &get_resolved_expr(node)->const_val;
4582 ErrorMsg *parent_err_msg = add_node_error(g, node, buf_sprintf("C import failed"));4477 if (ok_invocation && fn_table_entry && fn_table_entry->is_pure && fn_table_entry->want_pure != WantPureFalse) {
4583 for (size_t i = 0; i < errors.length; i += 1) {4478 if (fn_table_entry->anal_state == FnAnalStateReady) {
4584 ErrorMsg *err_msg = errors.at(i);4479 analyze_fn_body(g, fn_table_entry);
4585 err_msg_add_note(parent_err_msg, err_msg);4480 if (fn_table_entry->proto_node->data.fn_proto.skip) {
4481 return g->builtin_types.entry_invalid;
4482 }
4483 }
4484 if (all_args_const_expr) {
4485 if (fn_table_entry->is_pure && fn_table_entry->anal_state == FnAnalStateComplete) {
4486 if (eval_fn(g, node, fn_table_entry, result_val, 1000, struct_node)) {
4487 // function evaluation generated an error
4488 return g->builtin_types.entry_invalid;
4489 }
4490 return return_type;
4491 }
4586 }4492 }
4587
4588 return g->builtin_types.entry_invalid;
4589 }4493 }
45904494 if (!ok_invocation || !fn_table_entry || !fn_table_entry->is_pure || fn_table_entry->want_pure == WantPureFalse) {
4591 if (g->verbose) {4495 // calling an impure fn is impure
4592 fprintf(stderr, "\nc_import:\n");4496 mark_impure_fn(g, context, node);
4593 fprintf(stderr, "-----------\n");4497 if (fn_table_entry && fn_table_entry->want_pure == WantPureTrue) {
4594 ast_render(stderr, child_import->root, 4);4498 return g->builtin_types.entry_invalid;
4499 }
4595 }4500 }
45964501
4597 child_import->di_file = parent_import->di_file;4502 // TODO
4598 child_import->block_context = new_block_context(child_import->root, nullptr);4503 //if (handle_is_ptr(return_type)) {
4504 // if (context->fn_entry) {
4505 // context->fn_entry->cast_alloca_list.append(node);
4506 // } else if (!result_val->ok) {
4507 // add_node_error(g, node, buf_sprintf("unable to evaluate constant expression"));
4508 // }
4509 //}
45994510
4600 scan_decls(g, child_import, child_import->block_context, child_import->root);4511 return return_type;
4601 return resolve_expr_const_val_as_import(g, node, child_import);
4602}4512}
46034513
4604static TypeTableEntry *analyze_err_name(CodeGen *g, ImportTableEntry *import,4514static TypeTableEntry *analyze_fn_call_with_inline_args(CodeGen *g, ImportTableEntry *import,
4605 BlockContext *context, AstNode *node)4515 BlockContext *parent_context, TypeTableEntry *expected_type, AstNode *call_node,
4516 FnTableEntry *fn_table_entry, AstNode *struct_node)
4606{4517{
4607 assert(node->type == NodeTypeFnCallExpr);4518 assert(call_node->type == NodeTypeFnCallExpr);
46084519 assert(fn_table_entry);
4609 AstNode *err_value = node->data.fn_call_expr.params.at(0);
4610 TypeTableEntry *resolved_type = analyze_expression(g, import, context,
4611 g->builtin_types.entry_pure_error, err_value);
4612
4613 if (resolved_type->id == TypeTableEntryIdInvalid) {
4614 return resolved_type;
4615 }
4616
4617 g->generate_error_name_table = true;
46184520
4619 TypeTableEntry *str_type = get_slice_type(g, g->builtin_types.entry_u8, true);4521 AstNode *decl_node = fn_table_entry->proto_node;
4620 return str_type;
4621}
46224522
4623static TypeTableEntry *analyze_embed_file(CodeGen *g, ImportTableEntry *import,4523 // count parameters
4624 BlockContext *context, AstNode *node)4524 size_t struct_node_1_or_0 = (struct_node ? 1 : 0);
4625{4525 size_t src_param_count = decl_node->data.fn_proto.params.length;
4626 assert(node->type == NodeTypeFnCallExpr);4526 size_t call_param_count = call_node->data.fn_call_expr.params.length;
46274527
4628 AstNode **first_param_node = &node->data.fn_call_expr.params.at(0);4528 if (src_param_count != call_param_count + struct_node_1_or_0) {
4629 Buf *rel_file_path = resolve_const_expr_str(g, import, context, first_param_node);4529 add_node_error(g, call_node,
4630 if (!rel_file_path) {4530 buf_sprintf("expected %zu arguments, got %zu", src_param_count - struct_node_1_or_0, call_param_count));
4631 return g->builtin_types.entry_invalid;4531 return g->builtin_types.entry_invalid;
4632 }4532 }
46334533
4634 // figure out absolute path to resource4534 size_t inline_or_var_type_arg_count = decl_node->data.fn_proto.inline_or_var_type_arg_count;
4635 Buf source_dir_path = BUF_INIT;4535 assert(inline_or_var_type_arg_count > 0);
4636 os_path_dirname(import->path, &source_dir_path);4536
4537 BlockContext *child_context = decl_node->owner->block_context;
4538 size_t next_generic_param_index = 0;
46374539
4638 Buf file_path = BUF_INIT;4540 GenericFnTypeId *generic_fn_type_id = allocate<GenericFnTypeId>(1);
4639 os_path_resolve(&source_dir_path, rel_file_path, &file_path);4541 generic_fn_type_id->decl_node = decl_node;
4542 generic_fn_type_id->generic_param_count = inline_or_var_type_arg_count;
4543 generic_fn_type_id->generic_params = allocate<GenericParamValue>(inline_or_var_type_arg_count);
46404544
4641 // load from file system into const expr4545 size_t next_impl_i = 0;
4642 Buf file_contents = BUF_INIT;4546 for (size_t call_i = 0; call_i < call_param_count; call_i += 1) {
4643 int err;4547 size_t proto_i = call_i + struct_node_1_or_0;
4644 if ((err = os_fetch_file_path(&file_path, &file_contents))) {4548 AstNode *generic_param_decl_node = decl_node->data.fn_proto.params.at(proto_i);
4645 if (err == ErrorFileNotFound) {4549 assert(generic_param_decl_node->type == NodeTypeParamDecl);
4646 add_node_error(g, node,4550
4647 buf_sprintf("unable to find '%s'", buf_ptr(&file_path)));4551 AstNode **generic_param_type_node = &generic_param_decl_node->data.param_decl.type;
4648 return g->builtin_types.entry_invalid;4552 TypeTableEntry *expected_param_type = analyze_type_expr(g, decl_node->owner, child_context,
4649 } else {4553 *generic_param_type_node);
4650 add_node_error(g, node,4554 if (expected_param_type->id == TypeTableEntryIdInvalid) {
4651 buf_sprintf("unable to open '%s': %s", buf_ptr(&file_path), err_str(err)));4555 return expected_param_type;
4652 return g->builtin_types.entry_invalid;
4653 }4556 }
4654 }
46554557
4656 // TODO add dependency on the file we embedded so that we know if it changes4558 bool is_var_type = (expected_param_type->id == TypeTableEntryIdVar);
4657 // we'll have to invalidate the cache4559 bool is_inline = generic_param_decl_node->data.param_decl.is_inline;
46584560 if (!is_inline && !is_var_type) {
4659 return resolve_expr_const_val_as_string_lit(g, node, &file_contents);4561 next_impl_i += 1;
4660}4562 continue;
46614563 }
4662static TypeTableEntry *analyze_cmpxchg(CodeGen *g, ImportTableEntry *import,
4663 BlockContext *context, AstNode *node)
4664{
4665 assert(node->type == NodeTypeFnCallExpr);
4666
4667 AstNode **ptr_arg = &node->data.fn_call_expr.params.at(0);
4668 AstNode **cmp_arg = &node->data.fn_call_expr.params.at(1);
4669 AstNode **new_arg = &node->data.fn_call_expr.params.at(2);
4670 AstNode **success_order_arg = &node->data.fn_call_expr.params.at(3);
4671 AstNode **failure_order_arg = &node->data.fn_call_expr.params.at(4);
4672
4673 TypeTableEntry *ptr_type = analyze_expression(g, import, context, nullptr, *ptr_arg);
4674 if (ptr_type->id == TypeTableEntryIdInvalid) {
4675 return g->builtin_types.entry_invalid;
4676 } else if (ptr_type->id != TypeTableEntryIdPointer) {
4677 add_node_error(g, *ptr_arg,
4678 buf_sprintf("expected pointer argument, got '%s'", buf_ptr(&ptr_type->name)));
4679 return g->builtin_types.entry_invalid;
4680 }
4681
4682 TypeTableEntry *child_type = ptr_type->data.pointer.child_type;
4683 TypeTableEntry *cmp_type = analyze_expression(g, import, context, child_type, *cmp_arg);
4684 TypeTableEntry *new_type = analyze_expression(g, import, context, child_type, *new_arg);
4685
4686 TypeTableEntry *success_order_type = analyze_expression(g, import, context,
4687 g->builtin_types.entry_atomic_order_enum, *success_order_arg);
4688 TypeTableEntry *failure_order_type = analyze_expression(g, import, context,
4689 g->builtin_types.entry_atomic_order_enum, *failure_order_arg);
4690
4691 if (cmp_type->id == TypeTableEntryIdInvalid ||
4692 new_type->id == TypeTableEntryIdInvalid ||
4693 success_order_type->id == TypeTableEntryIdInvalid ||
4694 failure_order_type->id == TypeTableEntryIdInvalid)
4695 {
4696 return g->builtin_types.entry_invalid;
4697 }
4698
4699 ConstExprValue *success_order_val = &get_resolved_expr(*success_order_arg)->const_val;
4700 ConstExprValue *failure_order_val = &get_resolved_expr(*failure_order_arg)->const_val;
4701 if (!success_order_val->ok) {
4702 add_node_error(g, *success_order_arg, buf_sprintf("unable to evaluate constant expression"));
4703 return g->builtin_types.entry_invalid;
4704 } else if (!failure_order_val->ok) {
4705 add_node_error(g, *failure_order_arg, buf_sprintf("unable to evaluate constant expression"));
4706 return g->builtin_types.entry_invalid;
4707 }
4708
4709 if (success_order_val->data.x_enum.tag < AtomicOrderMonotonic) {
4710 add_node_error(g, *success_order_arg,
4711 buf_sprintf("success atomic ordering must be Monotonic or stricter"));
4712 return g->builtin_types.entry_invalid;
4713 }
4714 if (failure_order_val->data.x_enum.tag < AtomicOrderMonotonic) {
4715 add_node_error(g, *failure_order_arg,
4716 buf_sprintf("failure atomic ordering must be Monotonic or stricter"));
4717 return g->builtin_types.entry_invalid;
4718 }
4719 if (failure_order_val->data.x_enum.tag > success_order_val->data.x_enum.tag) {
4720 add_node_error(g, *failure_order_arg,
4721 buf_sprintf("failure atomic ordering must be no stricter than success"));
4722 return g->builtin_types.entry_invalid;
4723 }
4724 if (failure_order_val->data.x_enum.tag == AtomicOrderRelease ||
4725 failure_order_val->data.x_enum.tag == AtomicOrderAcqRel)
4726 {
4727 add_node_error(g, *failure_order_arg,
4728 buf_sprintf("failure atomic ordering must not be Release or AcqRel"));
4729 return g->builtin_types.entry_invalid;
4730 }
4731
4732 return g->builtin_types.entry_bool;
4733}
4734
4735static TypeTableEntry *analyze_fence(CodeGen *g, ImportTableEntry *import,
4736 BlockContext *context, AstNode *node)
4737{
4738 assert(node->type == NodeTypeFnCallExpr);
4739
4740 AstNode **atomic_order_arg = &node->data.fn_call_expr.params.at(0);
4741 TypeTableEntry *atomic_order_type = analyze_expression(g, import, context,
4742 g->builtin_types.entry_atomic_order_enum, *atomic_order_arg);
4743
4744 if (atomic_order_type->id == TypeTableEntryIdInvalid) {
4745 return g->builtin_types.entry_invalid;
4746 }
4747
4748 ConstExprValue *atomic_order_val = &get_resolved_expr(*atomic_order_arg)->const_val;
4749
4750 if (!atomic_order_val->ok) {
4751 add_node_error(g, *atomic_order_arg, buf_sprintf("unable to evaluate constant expression"));
4752 return g->builtin_types.entry_invalid;
4753 }
4754
4755 return g->builtin_types.entry_void;
4756}
4757
4758static TypeTableEntry *analyze_div_exact(CodeGen *g, ImportTableEntry *import,
4759 BlockContext *context, AstNode *node)
4760{
4761 assert(node->type == NodeTypeFnCallExpr);
4762
4763 AstNode **op1 = &node->data.fn_call_expr.params.at(0);
4764 AstNode **op2 = &node->data.fn_call_expr.params.at(1);
4765
4766 TypeTableEntry *op1_type = analyze_expression(g, import, context, nullptr, *op1);
4767 TypeTableEntry *op2_type = analyze_expression(g, import, context, nullptr, *op2);
4768
4769 AstNode *op_nodes[] = {*op1, *op2};
4770 TypeTableEntry *op_types[] = {op1_type, op2_type};
4771 TypeTableEntry *result_type = resolve_peer_type_compatibility(g, import, context, node,
4772 op_nodes, op_types, 2);
4773
4774 if (result_type->id == TypeTableEntryIdInvalid) {
4775 return g->builtin_types.entry_invalid;
4776 } else if (result_type->id == TypeTableEntryIdInt) {
4777 return result_type;
4778 } else if (result_type->id == TypeTableEntryIdNumLitInt) {
4779 // check for division by zero
4780 // check for non exact division
4781 zig_panic("TODO");
4782 } else {
4783 add_node_error(g, node,
4784 buf_sprintf("expected integer type, got '%s'", buf_ptr(&result_type->name)));
4785 return g->builtin_types.entry_invalid;
4786 }
4787}
4788
4789static TypeTableEntry *analyze_truncate(CodeGen *g, ImportTableEntry *import,
4790 BlockContext *context, AstNode *node)
4791{
4792 assert(node->type == NodeTypeFnCallExpr);
4793
4794 AstNode **op1 = &node->data.fn_call_expr.params.at(0);
4795 AstNode **op2 = &node->data.fn_call_expr.params.at(1);
4796
4797 TypeTableEntry *dest_type = analyze_type_expr(g, import, context, *op1);
4798 TypeTableEntry *src_type = analyze_expression(g, import, context, nullptr, *op2);
4799
4800 if (dest_type->id == TypeTableEntryIdInvalid || src_type->id == TypeTableEntryIdInvalid) {
4801 return g->builtin_types.entry_invalid;
4802 } else if (dest_type->id != TypeTableEntryIdInt) {
4803 add_node_error(g, *op1,
4804 buf_sprintf("expected integer type, got '%s'", buf_ptr(&dest_type->name)));
4805 return g->builtin_types.entry_invalid;
4806 } else if (src_type->id != TypeTableEntryIdInt) {
4807 add_node_error(g, *op2,
4808 buf_sprintf("expected integer type, got '%s'", buf_ptr(&src_type->name)));
4809 return g->builtin_types.entry_invalid;
4810 } else if (src_type->data.integral.is_signed != dest_type->data.integral.is_signed) {
4811 const char *sign_str = dest_type->data.integral.is_signed ? "signed" : "unsigned";
4812 add_node_error(g, *op2,
4813 buf_sprintf("expected %s integer type, got '%s'", sign_str, buf_ptr(&src_type->name)));
4814 return g->builtin_types.entry_invalid;
4815 } else if (src_type->data.integral.bit_count <= dest_type->data.integral.bit_count) {
4816 add_node_error(g, *op2,
4817 buf_sprintf("type '%s' has same or fewer bits than destination type '%s'",
4818 buf_ptr(&src_type->name), buf_ptr(&dest_type->name)));
4819 return g->builtin_types.entry_invalid;
4820 }
4821
4822 // TODO const expr eval
4823
4824 return dest_type;
4825}
4826
4827static TypeTableEntry *analyze_compile_err(CodeGen *g, ImportTableEntry *import,
4828 BlockContext *context, AstNode *node)
4829{
4830 AstNode *first_param_node = node->data.fn_call_expr.params.at(0);
4831 Buf *err_msg = resolve_const_expr_str(g, import, context, first_param_node->parent_field);
4832 if (!err_msg) {
4833 return g->builtin_types.entry_invalid;
4834 }
4835
4836 add_node_error(g, node, err_msg);
4837
4838 return g->builtin_types.entry_invalid;
4839}
4840
4841static TypeTableEntry *analyze_int_type(CodeGen *g, ImportTableEntry *import,
4842 BlockContext *context, AstNode *node)
4843{
4844 AstNode **is_signed_node = &node->data.fn_call_expr.params.at(0);
4845 AstNode **bit_count_node = &node->data.fn_call_expr.params.at(1);
4846
4847 TypeTableEntry *bool_type = g->builtin_types.entry_bool;
4848 TypeTableEntry *usize_type = g->builtin_types.entry_usize;
4849 TypeTableEntry *is_signed_type = analyze_expression(g, import, context, bool_type, *is_signed_node);
4850 TypeTableEntry *bit_count_type = analyze_expression(g, import, context, usize_type, *bit_count_node);
4851
4852 if (is_signed_type->id == TypeTableEntryIdInvalid ||
4853 bit_count_type->id == TypeTableEntryIdInvalid)
4854 {
4855 return g->builtin_types.entry_invalid;
4856 }
4857
4858 ConstExprValue *is_signed_val = &get_resolved_expr(*is_signed_node)->const_val;
4859 ConstExprValue *bit_count_val = &get_resolved_expr(*bit_count_node)->const_val;
4860
4861 AstNode *bad_node = nullptr;
4862 if (!is_signed_val->ok) {
4863 bad_node = *is_signed_node;
4864 } else if (!bit_count_val->ok) {
4865 bad_node = *bit_count_node;
4866 }
4867 if (bad_node) {
4868 add_node_error(g, bad_node, buf_sprintf("unable to evaluate constant expression"));
4869 return g->builtin_types.entry_invalid;
4870 }
4871
4872 bool depends_on_compile_var = is_signed_val->depends_on_compile_var || bit_count_val->depends_on_compile_var;
4873
4874 TypeTableEntry *int_type = get_int_type(g, is_signed_val->data.x_bool,
4875 bit_count_val->data.x_bignum.data.x_uint);
4876 return resolve_expr_const_val_as_type(g, node, int_type, depends_on_compile_var);
4877
4878}
4879
4880static TypeTableEntry *analyze_set_fn_test(CodeGen *g, ImportTableEntry *import,
4881 BlockContext *context, AstNode *node)
4882{
4883 AstNode **fn_node = &node->data.fn_call_expr.params.at(0);
4884 AstNode **value_node = &node->data.fn_call_expr.params.at(1);
4885
4886 FnTableEntry *fn_entry = resolve_const_expr_fn(g, import, context, fn_node);
4887 if (!fn_entry) {
4888 return g->builtin_types.entry_invalid;
4889 }
4890
4891 bool ok = resolve_const_expr_bool(g, import, context, value_node, &fn_entry->is_test);
4892 if (!ok) {
4893 return g->builtin_types.entry_invalid;
4894 }
4895
4896 if (fn_entry->fn_test_set_node) {
4897 ErrorMsg *msg = add_node_error(g, node, buf_sprintf("function test attribute set twice"));
4898 add_error_note(g, msg, fn_entry->fn_test_set_node, buf_sprintf("first set here"));
4899 return g->builtin_types.entry_invalid;
4900 }
4901 fn_entry->fn_test_set_node = node;
4902
4903 g->test_fn_count += 1;
4904 return g->builtin_types.entry_void;
4905}
4906
4907static TypeTableEntry *analyze_set_fn_no_inline(CodeGen *g, ImportTableEntry *import,
4908 BlockContext *context, AstNode *node)
4909{
4910 AstNode **fn_node = &node->data.fn_call_expr.params.at(0);
4911 AstNode **value_node = &node->data.fn_call_expr.params.at(1);
4912
4913 FnTableEntry *fn_entry = resolve_const_expr_fn(g, import, context, fn_node);
4914 if (!fn_entry) {
4915 return g->builtin_types.entry_invalid;
4916 }
4917
4918 bool is_noinline;
4919 bool ok = resolve_const_expr_bool(g, import, context, value_node, &is_noinline);
4920 if (!ok) {
4921 return g->builtin_types.entry_invalid;
4922 }
4923
4924 if (fn_entry->fn_no_inline_set_node) {
4925 ErrorMsg *msg = add_node_error(g, node, buf_sprintf("function no inline attribute set twice"));
4926 add_error_note(g, msg, fn_entry->fn_no_inline_set_node, buf_sprintf("first set here"));
4927 return g->builtin_types.entry_invalid;
4928 }
4929 fn_entry->fn_no_inline_set_node = node;
4930
4931 if (fn_entry->fn_inline == FnInlineAlways) {
4932 add_node_error(g, node, buf_sprintf("function is both inline and noinline"));
4933 fn_entry->proto_node->data.fn_proto.skip = true;
4934 return g->builtin_types.entry_invalid;
4935 } else if (is_noinline) {
4936 fn_entry->fn_inline = FnInlineNever;
4937 }
4938
4939 return g->builtin_types.entry_void;
4940}
4941
4942static TypeTableEntry *analyze_set_fn_static_eval(CodeGen *g, ImportTableEntry *import,
4943 BlockContext *context, AstNode *node)
4944{
4945 AstNode **fn_node = &node->data.fn_call_expr.params.at(0);
4946 AstNode **value_node = &node->data.fn_call_expr.params.at(1);
4947
4948 FnTableEntry *fn_entry = resolve_const_expr_fn(g, import, context, fn_node);
4949 if (!fn_entry) {
4950 return g->builtin_types.entry_invalid;
4951 }
4952
4953 bool want_static_eval;
4954 bool ok = resolve_const_expr_bool(g, import, context, value_node, &want_static_eval);
4955 if (!ok) {
4956 return g->builtin_types.entry_invalid;
4957 }
4958
4959 if (fn_entry->fn_static_eval_set_node) {
4960 ErrorMsg *msg = add_node_error(g, node, buf_sprintf("function static eval attribute set twice"));
4961 add_error_note(g, msg, fn_entry->fn_static_eval_set_node, buf_sprintf("first set here"));
4962 return g->builtin_types.entry_invalid;
4963 }
4964 fn_entry->fn_static_eval_set_node = node;
4965
4966 if (want_static_eval && !context->fn_entry->is_pure) {
4967 add_node_error(g, node, buf_sprintf("attribute appears too late within function"));
4968 return g->builtin_types.entry_invalid;
4969 }
4970
4971 if (want_static_eval) {
4972 fn_entry->want_pure = WantPureTrue;
4973 fn_entry->want_pure_attr_node = node;
4974 } else {
4975 fn_entry->want_pure = WantPureFalse;
4976 fn_entry->is_pure = false;
4977 }
4978
4979 return g->builtin_types.entry_void;
4980}
4981
4982static TypeTableEntry *analyze_set_fn_visible(CodeGen *g, ImportTableEntry *import,
4983 BlockContext *context, AstNode *node)
4984{
4985 AstNode **fn_node = &node->data.fn_call_expr.params.at(0);
4986 AstNode **value_node = &node->data.fn_call_expr.params.at(1);
4987
4988 FnTableEntry *fn_entry = resolve_const_expr_fn(g, import, context, fn_node);
4989 if (!fn_entry) {
4990 return g->builtin_types.entry_invalid;
4991 }
4992
4993 bool want_export;
4994 bool ok = resolve_const_expr_bool(g, import, context, value_node, &want_export);
4995 if (!ok) {
4996 return g->builtin_types.entry_invalid;
4997 }
4998
4999 if (fn_entry->fn_export_set_node) {
5000 ErrorMsg *msg = add_node_error(g, node, buf_sprintf("function visibility set twice"));
5001 add_error_note(g, msg, fn_entry->fn_export_set_node, buf_sprintf("first set here"));
5002 return g->builtin_types.entry_invalid;
5003 }
5004 fn_entry->fn_export_set_node = node;
5005
5006 AstNodeFnProto *fn_proto = &fn_entry->proto_node->data.fn_proto;
5007 if (fn_proto->top_level_decl.visib_mod != VisibModExport) {
5008 ErrorMsg *msg = add_node_error(g, node,
5009 buf_sprintf("function must be marked export to set function visibility"));
5010 add_error_note(g, msg, fn_entry->proto_node, buf_sprintf("function declared here"));
5011 return g->builtin_types.entry_void;
5012 }
5013 if (!want_export) {
5014 fn_proto->top_level_decl.visib_mod = VisibModPub;
5015 }
5016
5017 return g->builtin_types.entry_void;
5018}
5019
5020static TypeTableEntry *analyze_set_debug_safety(CodeGen *g, ImportTableEntry *import,
5021 BlockContext *parent_context, AstNode *node)
5022{
5023 AstNode **target_node = &node->data.fn_call_expr.params.at(0);
5024 AstNode **value_node = &node->data.fn_call_expr.params.at(1);
5025
5026 TypeTableEntry *target_type = analyze_expression(g, import, parent_context, nullptr, *target_node);
5027 BlockContext *target_context;
5028 ConstExprValue *const_val = &get_resolved_expr(*target_node)->const_val;
5029 if (target_type->id == TypeTableEntryIdInvalid) {
5030 return g->builtin_types.entry_invalid;
5031 }
5032 if (!const_val->ok) {
5033 add_node_error(g, *target_node, buf_sprintf("unable to evaluate constant expression"));
5034 return g->builtin_types.entry_invalid;
5035 }
5036 if (target_type->id == TypeTableEntryIdBlock) {
5037 target_context = const_val->data.x_block;
5038 } else if (target_type->id == TypeTableEntryIdFn) {
5039 target_context = const_val->data.x_fn->fn_def_node->data.fn_def.block_context;
5040 } else if (target_type->id == TypeTableEntryIdMetaType) {
5041 TypeTableEntry *type_arg = const_val->data.x_type;
5042 if (type_arg->id == TypeTableEntryIdStruct) {
5043 target_context = type_arg->data.structure.block_context;
5044 } else if (type_arg->id == TypeTableEntryIdEnum) {
5045 target_context = type_arg->data.enumeration.block_context;
5046 } else if (type_arg->id == TypeTableEntryIdUnion) {
5047 target_context = type_arg->data.unionation.block_context;
5048 } else {
5049 add_node_error(g, *target_node,
5050 buf_sprintf("expected scope reference, got type '%s'", buf_ptr(&type_arg->name)));
5051 return g->builtin_types.entry_invalid;
5052 }
5053 } else {
5054 add_node_error(g, *target_node,
5055 buf_sprintf("expected scope reference, got type '%s'", buf_ptr(&target_type->name)));
5056 return g->builtin_types.entry_invalid;
5057 }
5058
5059 bool want_debug_safety;
5060 bool ok = resolve_const_expr_bool(g, import, parent_context, value_node, &want_debug_safety);
5061 if (!ok) {
5062 return g->builtin_types.entry_invalid;
5063 }
5064
5065 if (target_context->safety_set_node) {
5066 ErrorMsg *msg = add_node_error(g, node, buf_sprintf("debug safety for scope set twice"));
5067 add_error_note(g, msg, target_context->safety_set_node, buf_sprintf("first set here"));
5068 return g->builtin_types.entry_invalid;
5069 }
5070 target_context->safety_set_node = node;
5071
5072 target_context->safety_off = !want_debug_safety;
5073
5074 return g->builtin_types.entry_void;
5075}
5076
5077static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
5078 TypeTableEntry *expected_type, AstNode *node)
5079{
5080 assert(node->type == NodeTypeFnCallExpr);
5081
5082 AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr;
5083 Buf *name = fn_ref_expr->data.symbol_expr.symbol;
5084
5085 auto entry = g->builtin_fn_table.maybe_get(name);
5086
5087 if (!entry) {
5088 add_node_error(g, node,
5089 buf_sprintf("invalid builtin function: '%s'", buf_ptr(name)));
5090 return g->builtin_types.entry_invalid;
5091 }
5092
5093 BuiltinFnEntry *builtin_fn = entry->value;
5094 size_t actual_param_count = node->data.fn_call_expr.params.length;
5095
5096 node->data.fn_call_expr.builtin_fn = builtin_fn;
5097
5098 if (builtin_fn->param_count != actual_param_count) {
5099 add_node_error(g, node,
5100 buf_sprintf("expected %zu arguments, got %zu",
5101 builtin_fn->param_count, actual_param_count));
5102 return g->builtin_types.entry_invalid;
5103 }
5104
5105 builtin_fn->ref_count += 1;
5106
5107 switch (builtin_fn->id) {
5108 case BuiltinFnIdInvalid:
5109 zig_unreachable();
5110 case BuiltinFnIdAddWithOverflow:
5111 case BuiltinFnIdSubWithOverflow:
5112 case BuiltinFnIdMulWithOverflow:
5113 case BuiltinFnIdShlWithOverflow:
5114 {
5115 AstNode *type_node = node->data.fn_call_expr.params.at(0);
5116 TypeTableEntry *int_type = analyze_type_expr(g, import, context, type_node);
5117 if (int_type->id == TypeTableEntryIdInvalid) {
5118 return g->builtin_types.entry_bool;
5119 } else if (int_type->id == TypeTableEntryIdInt) {
5120 AstNode *op1_node = node->data.fn_call_expr.params.at(1);
5121 AstNode *op2_node = node->data.fn_call_expr.params.at(2);
5122 AstNode *result_node = node->data.fn_call_expr.params.at(3);
5123
5124 analyze_expression(g, import, context, int_type, op1_node);
5125 analyze_expression(g, import, context, int_type, op2_node);
5126 analyze_expression(g, import, context, get_pointer_to_type(g, int_type, false),
5127 result_node);
5128 } else {
5129 add_node_error(g, type_node,
5130 buf_sprintf("expected integer type, got '%s'", buf_ptr(&int_type->name)));
5131 }
5132
5133 // TODO constant expression evaluation
5134
5135 return g->builtin_types.entry_bool;
5136 }
5137 case BuiltinFnIdMemcpy:
5138 {
5139 AstNode *dest_node = node->data.fn_call_expr.params.at(0);
5140 AstNode *src_node = node->data.fn_call_expr.params.at(1);
5141 AstNode *len_node = node->data.fn_call_expr.params.at(2);
5142 TypeTableEntry *dest_type = analyze_expression(g, import, context, nullptr, dest_node);
5143 TypeTableEntry *src_type = analyze_expression(g, import, context, nullptr, src_node);
5144 analyze_expression(g, import, context, builtin_fn->param_types[2], len_node);
5145
5146 if (dest_type->id != TypeTableEntryIdInvalid &&
5147 dest_type->id != TypeTableEntryIdPointer)
5148 {
5149 add_node_error(g, dest_node,
5150 buf_sprintf("expected pointer argument, got '%s'", buf_ptr(&dest_type->name)));
5151 }
5152
5153 if (src_type->id != TypeTableEntryIdInvalid &&
5154 src_type->id != TypeTableEntryIdPointer)
5155 {
5156 add_node_error(g, src_node,
5157 buf_sprintf("expected pointer argument, got '%s'", buf_ptr(&src_type->name)));
5158 }
5159
5160 if (dest_type->id == TypeTableEntryIdPointer &&
5161 src_type->id == TypeTableEntryIdPointer)
5162 {
5163 uint64_t dest_align = get_memcpy_align(g, dest_type->data.pointer.child_type);
5164 uint64_t src_align = get_memcpy_align(g, src_type->data.pointer.child_type);
5165 if (dest_align != src_align) {
5166 add_node_error(g, dest_node, buf_sprintf(
5167 "misaligned memcpy, '%s' has alignment '%" PRIu64 ", '%s' has alignment %" PRIu64,
5168 buf_ptr(&dest_type->name), dest_align,
5169 buf_ptr(&src_type->name), src_align));
5170 }
5171 }
5172
5173 return builtin_fn->return_type;
5174 }
5175 case BuiltinFnIdMemset:
5176 {
5177 AstNode *dest_node = node->data.fn_call_expr.params.at(0);
5178 AstNode *char_node = node->data.fn_call_expr.params.at(1);
5179 AstNode *len_node = node->data.fn_call_expr.params.at(2);
5180 TypeTableEntry *dest_type = analyze_expression(g, import, context, nullptr, dest_node);
5181 analyze_expression(g, import, context, builtin_fn->param_types[1], char_node);
5182 analyze_expression(g, import, context, builtin_fn->param_types[2], len_node);
5183
5184 if (dest_type->id != TypeTableEntryIdInvalid &&
5185 dest_type->id != TypeTableEntryIdPointer)
5186 {
5187 add_node_error(g, dest_node,
5188 buf_sprintf("expected pointer argument, got '%s'", buf_ptr(&dest_type->name)));
5189 }
5190
5191 return builtin_fn->return_type;
5192 }
5193 case BuiltinFnIdSizeof:
5194 {
5195 AstNode *type_node = node->data.fn_call_expr.params.at(0);
5196 TypeTableEntry *type_entry = analyze_type_expr(g, import, context, type_node);
5197 if (type_entry->id == TypeTableEntryIdInvalid) {
5198 return g->builtin_types.entry_invalid;
5199 } else if (type_entry->id == TypeTableEntryIdUnreachable) {
5200 add_node_error(g, first_executing_node(type_node),
5201 buf_sprintf("no size available for type '%s'", buf_ptr(&type_entry->name)));
5202 return g->builtin_types.entry_invalid;
5203 } else {
5204 uint64_t size_in_bytes = type_size(g, type_entry);
5205 bool depends_on_compile_var = (type_entry == g->builtin_types.entry_usize ||
5206 type_entry == g->builtin_types.entry_isize);
5207 return resolve_expr_const_val_as_unsigned_num_lit(g, node, expected_type,
5208 size_in_bytes, depends_on_compile_var);
5209 }
5210 }
5211 case BuiltinFnIdAlignof:
5212 {
5213 AstNode *type_node = node->data.fn_call_expr.params.at(0);
5214 TypeTableEntry *type_entry = analyze_type_expr(g, import, context, type_node);
5215 if (type_entry->id == TypeTableEntryIdInvalid) {
5216 return g->builtin_types.entry_invalid;
5217 } else if (type_entry->id == TypeTableEntryIdUnreachable) {
5218 add_node_error(g, first_executing_node(type_node),
5219 buf_sprintf("no align available for type '%s'", buf_ptr(&type_entry->name)));
5220 return g->builtin_types.entry_invalid;
5221 } else {
5222 uint64_t align_in_bytes = LLVMABISizeOfType(g->target_data_ref, type_entry->type_ref);
5223 return resolve_expr_const_val_as_unsigned_num_lit(g, node, expected_type,
5224 align_in_bytes, false);
5225 }
5226 }
5227 case BuiltinFnIdMaxValue:
5228 return analyze_min_max_value(g, import, context, node,
5229 "no max value available for type '%s'", true);
5230 case BuiltinFnIdMinValue:
5231 return analyze_min_max_value(g, import, context, node,
5232 "no min value available for type '%s'", false);
5233 case BuiltinFnIdMemberCount:
5234 {
5235 AstNode *type_node = node->data.fn_call_expr.params.at(0);
5236 TypeTableEntry *type_entry = analyze_type_expr(g, import, context, type_node);
5237
5238 if (type_entry->id == TypeTableEntryIdInvalid) {
5239 return type_entry;
5240 } else if (type_entry->id == TypeTableEntryIdEnum) {
5241 uint64_t value_count = type_entry->data.enumeration.src_field_count;
5242 return resolve_expr_const_val_as_unsigned_num_lit(g, node, expected_type,
5243 value_count, false);
5244 } else {
5245 add_node_error(g, node,
5246 buf_sprintf("no value count available for type '%s'", buf_ptr(&type_entry->name)));
5247 return g->builtin_types.entry_invalid;
5248 }
5249 }
5250 case BuiltinFnIdTypeof:
5251 {
5252 AstNode *expr_node = node->data.fn_call_expr.params.at(0);
5253 TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, expr_node);
5254
5255 switch (type_entry->id) {
5256 case TypeTableEntryIdInvalid:
5257 return type_entry;
5258 case TypeTableEntryIdNumLitFloat:
5259 case TypeTableEntryIdNumLitInt:
5260 case TypeTableEntryIdUndefLit:
5261 case TypeTableEntryIdNullLit:
5262 case TypeTableEntryIdNamespace:
5263 case TypeTableEntryIdBlock:
5264 case TypeTableEntryIdGenericFn:
5265 case TypeTableEntryIdVar:
5266 add_node_error(g, expr_node,
5267 buf_sprintf("type '%s' not eligible for @typeOf", buf_ptr(&type_entry->name)));
5268 return g->builtin_types.entry_invalid;
5269 case TypeTableEntryIdMetaType:
5270 case TypeTableEntryIdVoid:
5271 case TypeTableEntryIdBool:
5272 case TypeTableEntryIdUnreachable:
5273 case TypeTableEntryIdInt:
5274 case TypeTableEntryIdFloat:
5275 case TypeTableEntryIdPointer:
5276 case TypeTableEntryIdArray:
5277 case TypeTableEntryIdStruct:
5278 case TypeTableEntryIdMaybe:
5279 case TypeTableEntryIdErrorUnion:
5280 case TypeTableEntryIdPureError:
5281 case TypeTableEntryIdEnum:
5282 case TypeTableEntryIdUnion:
5283 case TypeTableEntryIdFn:
5284 case TypeTableEntryIdTypeDecl:
5285 return resolve_expr_const_val_as_type(g, node, type_entry, false);
5286 }
5287 }
5288 case BuiltinFnIdCInclude:
5289 {
5290 if (!context->c_import_buf) {
5291 add_node_error(g, node, buf_sprintf("@c_include valid only in c_import blocks"));
5292 return g->builtin_types.entry_invalid;
5293 }
5294
5295 AstNode **str_node = node->data.fn_call_expr.params.at(0)->parent_field;
5296 TypeTableEntry *str_type = get_slice_type(g, g->builtin_types.entry_u8, true);
5297 TypeTableEntry *resolved_type = analyze_expression(g, import, context, str_type, *str_node);
5298
5299 if (resolved_type->id == TypeTableEntryIdInvalid) {
5300 return resolved_type;
5301 }
5302
5303 ConstExprValue *const_str_val = &get_resolved_expr(*str_node)->const_val;
5304
5305 if (!const_str_val->ok) {
5306 add_node_error(g, *str_node, buf_sprintf("@c_include requires constant expression"));
5307 return g->builtin_types.entry_void;
5308 }
5309
5310 buf_appendf(context->c_import_buf, "#include <");
5311 ConstExprValue *ptr_field = const_str_val->data.x_struct.fields[0];
5312 uint64_t len = ptr_field->data.x_ptr.len;
5313 for (uint64_t i = 0; i < len; i += 1) {
5314 ConstExprValue *char_val = ptr_field->data.x_ptr.ptr[i];
5315 uint64_t big_c = char_val->data.x_bignum.data.x_uint;
5316 assert(big_c <= UINT8_MAX);
5317 uint8_t c = big_c;
5318 buf_append_char(context->c_import_buf, c);
5319 }
5320 buf_appendf(context->c_import_buf, ">\n");
5321
5322 return g->builtin_types.entry_void;
5323 }
5324 case BuiltinFnIdCDefine:
5325 zig_panic("TODO");
5326 case BuiltinFnIdCUndef:
5327 zig_panic("TODO");
5328
5329 case BuiltinFnIdCompileVar:
5330 {
5331 AstNode **str_node = node->data.fn_call_expr.params.at(0)->parent_field;
5332
5333 Buf *var_name = resolve_const_expr_str(g, import, context, str_node);
5334 if (!var_name) {
5335 return g->builtin_types.entry_invalid;
5336 }
5337
5338 ConstExprValue *const_val = &get_resolved_expr(node)->const_val;
5339 const_val->ok = true;
5340 const_val->depends_on_compile_var = true;
5341
5342 if (buf_eql_str(var_name, "is_big_endian")) {
5343 return resolve_expr_const_val_as_bool(g, node, g->is_big_endian, true);
5344 } else if (buf_eql_str(var_name, "is_release")) {
5345 return resolve_expr_const_val_as_bool(g, node, g->is_release_build, true);
5346 } else if (buf_eql_str(var_name, "is_test")) {
5347 return resolve_expr_const_val_as_bool(g, node, g->is_test_build, true);
5348 } else if (buf_eql_str(var_name, "os")) {
5349 const_val->data.x_enum.tag = g->target_os_index;
5350 return g->builtin_types.entry_os_enum;
5351 } else if (buf_eql_str(var_name, "arch")) {
5352 const_val->data.x_enum.tag = g->target_arch_index;
5353 return g->builtin_types.entry_arch_enum;
5354 } else if (buf_eql_str(var_name, "environ")) {
5355 const_val->data.x_enum.tag = g->target_environ_index;
5356 return g->builtin_types.entry_environ_enum;
5357 } else if (buf_eql_str(var_name, "object_format")) {
5358 const_val->data.x_enum.tag = g->target_oformat_index;
5359 return g->builtin_types.entry_oformat_enum;
5360 } else {
5361 add_node_error(g, *str_node,
5362 buf_sprintf("unrecognized compile variable: '%s'", buf_ptr(var_name)));
5363 return g->builtin_types.entry_invalid;
5364 }
5365 }
5366 case BuiltinFnIdConstEval:
5367 {
5368 AstNode **expr_node = node->data.fn_call_expr.params.at(0)->parent_field;
5369 TypeTableEntry *resolved_type = analyze_expression(g, import, context, expected_type, *expr_node);
5370 if (resolved_type->id == TypeTableEntryIdInvalid) {
5371 return resolved_type;
5372 }
5373
5374 ConstExprValue *const_expr_val = &get_resolved_expr(*expr_node)->const_val;
5375
5376 if (!const_expr_val->ok) {
5377 add_node_error(g, *expr_node, buf_sprintf("unable to evaluate constant expression"));
5378 return g->builtin_types.entry_invalid;
5379 }
5380
5381 ConstExprValue *const_val = &get_resolved_expr(node)->const_val;
5382 *const_val = *const_expr_val;
5383
5384 return resolved_type;
5385 }
5386 case BuiltinFnIdCtz:
5387 case BuiltinFnIdClz:
5388 {
5389 AstNode *type_node = node->data.fn_call_expr.params.at(0);
5390 TypeTableEntry *int_type = analyze_type_expr(g, import, context, type_node);
5391 if (int_type->id == TypeTableEntryIdInvalid) {
5392 return int_type;
5393 } else if (int_type->id == TypeTableEntryIdInt) {
5394 AstNode **expr_node = node->data.fn_call_expr.params.at(1)->parent_field;
5395 TypeTableEntry *resolved_type = analyze_expression(g, import, context, int_type, *expr_node);
5396 if (resolved_type->id == TypeTableEntryIdInvalid) {
5397 return resolved_type;
5398 }
5399
5400 // TODO const expr eval
5401
5402 return resolved_type;
5403 } else {
5404 add_node_error(g, type_node,
5405 buf_sprintf("expected integer type, got '%s'", buf_ptr(&int_type->name)));
5406 return g->builtin_types.entry_invalid;
5407 }
5408 }
5409 case BuiltinFnIdImport:
5410 return analyze_import(g, import, context, node);
5411 case BuiltinFnIdCImport:
5412 return analyze_c_import(g, import, context, node);
5413 case BuiltinFnIdErrName:
5414 return analyze_err_name(g, import, context, node);
5415 case BuiltinFnIdBreakpoint:
5416 mark_impure_fn(g, context, node);
5417 return g->builtin_types.entry_void;
5418 case BuiltinFnIdReturnAddress:
5419 case BuiltinFnIdFrameAddress:
5420 mark_impure_fn(g, context, node);
5421 return builtin_fn->return_type;
5422 case BuiltinFnIdEmbedFile:
5423 return analyze_embed_file(g, import, context, node);
5424 case BuiltinFnIdCmpExchange:
5425 return analyze_cmpxchg(g, import, context, node);
5426 case BuiltinFnIdFence:
5427 return analyze_fence(g, import, context, node);
5428 case BuiltinFnIdDivExact:
5429 return analyze_div_exact(g, import, context, node);
5430 case BuiltinFnIdTruncate:
5431 return analyze_truncate(g, import, context, node);
5432 case BuiltinFnIdCompileErr:
5433 return analyze_compile_err(g, import, context, node);
5434 case BuiltinFnIdIntType:
5435 return analyze_int_type(g, import, context, node);
5436 case BuiltinFnIdUnreachable:
5437 return g->builtin_types.entry_unreachable;
5438 case BuiltinFnIdSetFnTest:
5439 return analyze_set_fn_test(g, import, context, node);
5440 case BuiltinFnIdSetFnNoInline:
5441 return analyze_set_fn_no_inline(g, import, context, node);
5442 case BuiltinFnIdSetFnStaticEval:
5443 return analyze_set_fn_static_eval(g, import, context, node);
5444 case BuiltinFnIdSetFnVisible:
5445 return analyze_set_fn_visible(g, import, context, node);
5446 case BuiltinFnIdSetDebugSafety:
5447 return analyze_set_debug_safety(g, import, context, node);
5448 }
5449 zig_unreachable();
5450}
5451
5452static TypeTableEntry *bad_method_call(CodeGen *g, AstNode *node, TypeTableEntry *container_type,
5453 TypeTableEntry *expected_param_type, FnTableEntry *fn_table_entry)
5454{
5455 ErrorMsg *msg = add_node_error(g, node,
5456 buf_sprintf("function called as method of '%s', but first parameter is of type '%s'",
5457 buf_ptr(&container_type->name),
5458 buf_ptr(&expected_param_type->name)));
5459 if (fn_table_entry) {
5460 add_error_note(g, msg, fn_table_entry->proto_node, buf_sprintf("function declared here"));
5461 }
5462 return g->builtin_types.entry_invalid;
5463}
5464
5465// Before calling this function, set node->data.fn_call_expr.fn_table_entry if the function is known
5466// at compile time. Otherwise this is a function pointer call.
5467static TypeTableEntry *analyze_fn_call_ptr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
5468 TypeTableEntry *expected_type, AstNode *node, TypeTableEntry *fn_type,
5469 AstNode *struct_node)
5470{
5471 assert(node->type == NodeTypeFnCallExpr);
5472
5473 if (fn_type->id == TypeTableEntryIdInvalid) {
5474 return fn_type;
5475 }
5476
5477 // The function call might include inline parameters which we need to ignore according to the
5478 // fn_type.
5479 FnTableEntry *fn_table_entry = node->data.fn_call_expr.fn_entry;
5480 AstNode *generic_proto_node = fn_table_entry ?
5481 fn_table_entry->proto_node->data.fn_proto.generic_proto_node : nullptr;
5482
5483 // count parameters
5484 size_t struct_node_1_or_0 = struct_node ? 1 : 0;
5485 size_t src_param_count = fn_type->data.fn.fn_type_id.param_count +
5486 (generic_proto_node ? generic_proto_node->data.fn_proto.inline_arg_count : 0);
5487 size_t call_param_count = node->data.fn_call_expr.params.length;
5488 size_t expect_arg_count = src_param_count - struct_node_1_or_0;
5489
5490 bool ok_invocation = true;
5491
5492 if (fn_type->data.fn.fn_type_id.is_var_args) {
5493 if (call_param_count < expect_arg_count) {
5494 ok_invocation = false;
5495 add_node_error(g, node,
5496 buf_sprintf("expected at least %zu arguments, got %zu", src_param_count, call_param_count));
5497 }
5498 } else if (expect_arg_count != call_param_count) {
5499 ok_invocation = false;
5500 add_node_error(g, node,
5501 buf_sprintf("expected %zu arguments, got %zu", expect_arg_count, call_param_count));
5502 }
5503
5504 bool all_args_const_expr = true;
5505
5506 if (struct_node) {
5507 Expr *struct_expr = get_resolved_expr(struct_node);
5508 ConstExprValue *struct_const_val = &struct_expr->const_val;
5509 if (!struct_const_val->ok) {
5510 all_args_const_expr = false;
5511 }
5512
5513 FnTypeParamInfo *param_info = &fn_type->data.fn.fn_type_id.param_info[0];
5514 TypeTableEntry *expected_param_type = param_info->type;
5515 TypeTableEntry *container_bare_type = container_ref_type(struct_expr->type_entry);
5516 if (is_container_ref(expected_param_type)) {
5517 TypeTableEntry *param_bare_type = container_ref_type(expected_param_type);
5518 if (param_bare_type != container_bare_type) {
5519 return bad_method_call(g, node, container_bare_type, expected_param_type, fn_table_entry);
5520 }
5521 } else {
5522 return bad_method_call(g, node, container_bare_type, expected_param_type, fn_table_entry);
5523 }
5524 }
5525
5526 // analyze each parameter. in the case of a method, we already analyzed the
5527 // first parameter in order to figure out which struct we were calling a method on.
5528 size_t next_type_i = struct_node_1_or_0;
5529 for (size_t call_i = 0; call_i < call_param_count; call_i += 1) {
5530 size_t proto_i = call_i + struct_node_1_or_0;
5531 AstNode **param_node = &node->data.fn_call_expr.params.at(call_i);
5532 // determine the expected type for each parameter
5533 TypeTableEntry *expected_param_type = nullptr;
5534 if (proto_i < src_param_count) {
5535 if (generic_proto_node &&
5536 generic_proto_node->data.fn_proto.params.at(proto_i)->data.param_decl.is_inline)
5537 {
5538 continue;
5539 }
5540
5541 FnTypeParamInfo *param_info = &fn_type->data.fn.fn_type_id.param_info[next_type_i];
5542 next_type_i += 1;
5543
5544 expected_param_type = param_info->type;
5545 }
5546 TypeTableEntry *param_type = analyze_expression(g, import, context, expected_param_type, *param_node);
5547 if (param_type->id == TypeTableEntryIdInvalid) {
5548 return param_type;
5549 }
5550
5551 ConstExprValue *const_arg_val = &get_resolved_expr(*param_node)->const_val;
5552 if (!const_arg_val->ok) {
5553 all_args_const_expr = false;
5554 }
5555 }
5556
5557 TypeTableEntry *return_type = fn_type->data.fn.fn_type_id.return_type;
5558
5559 if (return_type->id == TypeTableEntryIdInvalid) {
5560 return return_type;
5561 }
5562
5563 ConstExprValue *result_val = &get_resolved_expr(node)->const_val;
5564 if (ok_invocation && fn_table_entry && fn_table_entry->is_pure && fn_table_entry->want_pure != WantPureFalse) {
5565 if (fn_table_entry->anal_state == FnAnalStateReady) {
5566 analyze_fn_body(g, fn_table_entry);
5567 if (fn_table_entry->proto_node->data.fn_proto.skip) {
5568 return g->builtin_types.entry_invalid;
5569 }
5570 }
5571 if (all_args_const_expr) {
5572 if (fn_table_entry->is_pure && fn_table_entry->anal_state == FnAnalStateComplete) {
5573 if (eval_fn(g, node, fn_table_entry, result_val, 1000, struct_node)) {
5574 // function evaluation generated an error
5575 return g->builtin_types.entry_invalid;
5576 }
5577 return return_type;
5578 }
5579 }
5580 }
5581 if (!ok_invocation || !fn_table_entry || !fn_table_entry->is_pure || fn_table_entry->want_pure == WantPureFalse) {
5582 // calling an impure fn is impure
5583 mark_impure_fn(g, context, node);
5584 if (fn_table_entry && fn_table_entry->want_pure == WantPureTrue) {
5585 return g->builtin_types.entry_invalid;
5586 }
5587 }
5588
5589 // TODO
5590 //if (handle_is_ptr(return_type)) {
5591 // if (context->fn_entry) {
5592 // context->fn_entry->cast_alloca_list.append(node);
5593 // } else if (!result_val->ok) {
5594 // add_node_error(g, node, buf_sprintf("unable to evaluate constant expression"));
5595 // }
5596 //}
5597
5598 return return_type;
5599}
5600
5601static TypeTableEntry *analyze_fn_call_with_inline_args(CodeGen *g, ImportTableEntry *import,
5602 BlockContext *parent_context, TypeTableEntry *expected_type, AstNode *call_node,
5603 FnTableEntry *fn_table_entry, AstNode *struct_node)
5604{
5605 assert(call_node->type == NodeTypeFnCallExpr);
5606 assert(fn_table_entry);
5607
5608 AstNode *decl_node = fn_table_entry->proto_node;
5609
5610 // count parameters
5611 size_t struct_node_1_or_0 = (struct_node ? 1 : 0);
5612 size_t src_param_count = decl_node->data.fn_proto.params.length;
5613 size_t call_param_count = call_node->data.fn_call_expr.params.length;
5614
5615 if (src_param_count != call_param_count + struct_node_1_or_0) {
5616 add_node_error(g, call_node,
5617 buf_sprintf("expected %zu arguments, got %zu", src_param_count - struct_node_1_or_0, call_param_count));
5618 return g->builtin_types.entry_invalid;
5619 }
5620
5621 size_t inline_or_var_type_arg_count = decl_node->data.fn_proto.inline_or_var_type_arg_count;
5622 assert(inline_or_var_type_arg_count > 0);
5623
5624 BlockContext *child_context = decl_node->owner->block_context;
5625 size_t next_generic_param_index = 0;
5626
5627 GenericFnTypeId *generic_fn_type_id = allocate<GenericFnTypeId>(1);
5628 generic_fn_type_id->decl_node = decl_node;
5629 generic_fn_type_id->generic_param_count = inline_or_var_type_arg_count;
5630 generic_fn_type_id->generic_params = allocate<GenericParamValue>(inline_or_var_type_arg_count);
5631
5632 size_t next_impl_i = 0;
5633 for (size_t call_i = 0; call_i < call_param_count; call_i += 1) {
5634 size_t proto_i = call_i + struct_node_1_or_0;
5635 AstNode *generic_param_decl_node = decl_node->data.fn_proto.params.at(proto_i);
5636 assert(generic_param_decl_node->type == NodeTypeParamDecl);
5637
5638 AstNode **generic_param_type_node = &generic_param_decl_node->data.param_decl.type;
5639 TypeTableEntry *expected_param_type = analyze_type_expr(g, decl_node->owner, child_context,
5640 *generic_param_type_node);
5641 if (expected_param_type->id == TypeTableEntryIdInvalid) {
5642 return expected_param_type;
5643 }
5644
5645 bool is_var_type = (expected_param_type->id == TypeTableEntryIdVar);
5646 bool is_inline = generic_param_decl_node->data.param_decl.is_inline;
5647 if (!is_inline && !is_var_type) {
5648 next_impl_i += 1;
5649 continue;
5650 }
56514564
56524565
5653 AstNode **param_node = &call_node->data.fn_call_expr.params.at(call_i);4566 AstNode **param_node = &call_node->data.fn_call_expr.params.at(call_i);
...@@ -5817,7 +4730,7 @@ static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import...@@ -5817,7 +4730,7 @@ static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import
5817 AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr;4730 AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr;
58184731
5819 if (node->data.fn_call_expr.is_builtin) {4732 if (node->data.fn_call_expr.is_builtin) {
5820 return analyze_builtin_fn_call_expr(g, import, context, expected_type, node);4733 zig_panic("moved builtin fn call code to ir.cpp");
5821 }4734 }
58224735
5823 TypeTableEntry *invoke_type_entry = analyze_expression(g, import, context, nullptr, fn_ref_expr);4736 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...@@ -5885,222 +4798,6 @@ static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import
5885 }4798 }
5886}4799}
58874800
5888static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
5889 TypeTableEntry *expected_type, AstNode *node)
5890{
5891 PrefixOp prefix_op = node->data.prefix_op_expr.prefix_op;
5892 AstNode **expr_node = &node->data.prefix_op_expr.primary_expr;
5893 switch (prefix_op) {
5894 case PrefixOpInvalid:
5895 zig_unreachable();
5896 case PrefixOpBoolNot:
5897 {
5898 TypeTableEntry *type_entry = analyze_expression(g, import, context, g->builtin_types.entry_bool,
5899 *expr_node);
5900 if (type_entry->id == TypeTableEntryIdInvalid) {
5901 return g->builtin_types.entry_bool;
5902 }
5903
5904 ConstExprValue *target_const_val = &get_resolved_expr(*expr_node)->const_val;
5905 if (!target_const_val->ok) {
5906 return g->builtin_types.entry_bool;
5907 }
5908
5909 bool answer = !target_const_val->data.x_bool;
5910 return resolve_expr_const_val_as_bool(g, node, answer, target_const_val->depends_on_compile_var);
5911 }
5912 case PrefixOpBinNot:
5913 {
5914 TypeTableEntry *expr_type = analyze_expression(g, import, context, expected_type,
5915 *expr_node);
5916 if (expr_type->id == TypeTableEntryIdInvalid) {
5917 return expr_type;
5918 } else if (expr_type->id == TypeTableEntryIdInt) {
5919 return expr_type;
5920 } else {
5921 add_node_error(g, node, buf_sprintf("unable to perform binary not operation on type '%s'",
5922 buf_ptr(&expr_type->name)));
5923 return g->builtin_types.entry_invalid;
5924 }
5925 // TODO const expr eval
5926 }
5927 case PrefixOpNegation:
5928 case PrefixOpNegationWrap:
5929 {
5930 TypeTableEntry *expr_type = analyze_expression(g, import, context, nullptr, *expr_node);
5931 if (expr_type->id == TypeTableEntryIdInvalid) {
5932 return expr_type;
5933 } else if ((expr_type->id == TypeTableEntryIdInt &&
5934 expr_type->data.integral.is_signed) ||
5935 expr_type->id == TypeTableEntryIdNumLitInt ||
5936 ((expr_type->id == TypeTableEntryIdFloat ||
5937 expr_type->id == TypeTableEntryIdNumLitFloat) &&
5938 prefix_op != PrefixOpNegationWrap))
5939 {
5940 ConstExprValue *target_const_val = &get_resolved_expr(*expr_node)->const_val;
5941 if (!target_const_val->ok) {
5942 return expr_type;
5943 }
5944 ConstExprValue *const_val = &get_resolved_expr(node)->const_val;
5945 const_val->ok = true;
5946 const_val->depends_on_compile_var = target_const_val->depends_on_compile_var;
5947 bignum_negate(&const_val->data.x_bignum, &target_const_val->data.x_bignum);
5948 if (expr_type->id == TypeTableEntryIdFloat ||
5949 expr_type->id == TypeTableEntryIdNumLitFloat ||
5950 expr_type->id == TypeTableEntryIdNumLitInt)
5951 {
5952 return expr_type;
5953 }
5954
5955 bool overflow = !bignum_fits_in_bits(&const_val->data.x_bignum,
5956 expr_type->data.integral.bit_count, expr_type->data.integral.is_signed);
5957 if (prefix_op == PrefixOpNegationWrap) {
5958 if (overflow) {
5959 const_val->data.x_bignum.is_negative = true;
5960 }
5961 } else if (overflow) {
5962 add_node_error(g, *expr_node, buf_sprintf("negation caused overflow"));
5963 return g->builtin_types.entry_invalid;
5964 }
5965 return expr_type;
5966 } else {
5967 const char *fmt = (prefix_op == PrefixOpNegationWrap) ?
5968 "invalid wrapping negation type: '%s'" : "invalid negation type: '%s'";
5969 add_node_error(g, node, buf_sprintf(fmt, buf_ptr(&expr_type->name)));
5970 return g->builtin_types.entry_invalid;
5971 }
5972 }
5973 case PrefixOpAddressOf:
5974 case PrefixOpConstAddressOf:
5975 {
5976 bool is_const = (prefix_op == PrefixOpConstAddressOf);
5977
5978 TypeTableEntry *child_type = analyze_lvalue(g, import, context,
5979 *expr_node, LValPurposeAddressOf, is_const);
5980
5981 if (child_type->id == TypeTableEntryIdInvalid) {
5982 return g->builtin_types.entry_invalid;
5983 } else if (child_type->id == TypeTableEntryIdMetaType) {
5984 TypeTableEntry *meta_type = analyze_type_expr_pointer_only(g, import, context,
5985 *expr_node, true);
5986 if (meta_type->id == TypeTableEntryIdInvalid) {
5987 return g->builtin_types.entry_invalid;
5988 } else if (meta_type->id == TypeTableEntryIdUnreachable) {
5989 add_node_error(g, node, buf_create_from_str("pointer to unreachable not allowed"));
5990 return g->builtin_types.entry_invalid;
5991 } else {
5992 return resolve_expr_const_val_as_type(g, node,
5993 get_pointer_to_type(g, meta_type, is_const), false);
5994 }
5995 } else if (child_type->id == TypeTableEntryIdNumLitInt ||
5996 child_type->id == TypeTableEntryIdNumLitFloat)
5997 {
5998 add_node_error(g, *expr_node,
5999 buf_sprintf("unable to get address of type '%s'", buf_ptr(&child_type->name)));
6000 return g->builtin_types.entry_invalid;
6001 } else {
6002 return get_pointer_to_type(g, child_type, is_const);
6003 }
6004 }
6005 case PrefixOpDereference:
6006 {
6007 TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, *expr_node);
6008 if (type_entry->id == TypeTableEntryIdInvalid) {
6009 return type_entry;
6010 } else if (type_entry->id == TypeTableEntryIdPointer) {
6011 return type_entry->data.pointer.child_type;
6012 } else {
6013 add_node_error(g, *expr_node,
6014 buf_sprintf("indirection requires pointer operand ('%s' invalid)",
6015 buf_ptr(&type_entry->name)));
6016 return g->builtin_types.entry_invalid;
6017 }
6018 }
6019 case PrefixOpMaybe:
6020 {
6021 TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, *expr_node);
6022
6023 if (type_entry->id == TypeTableEntryIdInvalid) {
6024 return type_entry;
6025 } else if (type_entry->id == TypeTableEntryIdMetaType) {
6026 TypeTableEntry *meta_type = resolve_type(g, *expr_node);
6027 if (meta_type->id == TypeTableEntryIdInvalid) {
6028 return g->builtin_types.entry_invalid;
6029 } else if (meta_type->id == TypeTableEntryIdUnreachable) {
6030 add_node_error(g, node, buf_create_from_str("unable to wrap unreachable in maybe type"));
6031 return g->builtin_types.entry_invalid;
6032 } else {
6033 return resolve_expr_const_val_as_type(g, node, get_maybe_type(g, meta_type), false);
6034 }
6035 } else if (type_entry->id == TypeTableEntryIdUnreachable) {
6036 add_node_error(g, *expr_node, buf_sprintf("unable to wrap unreachable in maybe type"));
6037 return g->builtin_types.entry_invalid;
6038 } else {
6039 ConstExprValue *target_const_val = &get_resolved_expr(*expr_node)->const_val;
6040 TypeTableEntry *maybe_type = get_maybe_type(g, type_entry);
6041 if (!target_const_val->ok) {
6042 return maybe_type;
6043 }
6044 return resolve_expr_const_val_as_non_null(g, node, maybe_type, target_const_val);
6045 }
6046 }
6047 case PrefixOpError:
6048 {
6049 TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, *expr_node);
6050
6051 if (type_entry->id == TypeTableEntryIdInvalid) {
6052 return type_entry;
6053 } else if (type_entry->id == TypeTableEntryIdMetaType) {
6054 TypeTableEntry *meta_type = resolve_type(g, *expr_node);
6055 if (meta_type->id == TypeTableEntryIdInvalid) {
6056 return meta_type;
6057 } else if (meta_type->id == TypeTableEntryIdUnreachable) {
6058 add_node_error(g, node, buf_create_from_str("unable to wrap unreachable in error type"));
6059 return g->builtin_types.entry_invalid;
6060 } else {
6061 return resolve_expr_const_val_as_type(g, node, get_error_type(g, meta_type), false);
6062 }
6063 } else if (type_entry->id == TypeTableEntryIdUnreachable) {
6064 add_node_error(g, *expr_node, buf_sprintf("unable to wrap unreachable in error type"));
6065 return g->builtin_types.entry_invalid;
6066 } else {
6067 // TODO eval const expr
6068 return get_error_type(g, type_entry);
6069 }
6070
6071 }
6072 case PrefixOpUnwrapError:
6073 {
6074 TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, *expr_node);
6075
6076 if (type_entry->id == TypeTableEntryIdInvalid) {
6077 return type_entry;
6078 } else if (type_entry->id == TypeTableEntryIdErrorUnion) {
6079 return type_entry->data.error.child_type;
6080 } else {
6081 add_node_error(g, *expr_node,
6082 buf_sprintf("expected error type, got '%s'", buf_ptr(&type_entry->name)));
6083 return g->builtin_types.entry_invalid;
6084 }
6085 }
6086 case PrefixOpUnwrapMaybe:
6087 {
6088 TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, *expr_node);
6089
6090 if (type_entry->id == TypeTableEntryIdInvalid) {
6091 return type_entry;
6092 } else if (type_entry->id == TypeTableEntryIdMaybe) {
6093 return type_entry->data.maybe.child_type;
6094 } else {
6095 add_node_error(g, *expr_node,
6096 buf_sprintf("expected maybe type, got '%s'", buf_ptr(&type_entry->name)));
6097 return g->builtin_types.entry_invalid;
6098 }
6099 }
6100 }
6101 zig_unreachable();
6102}
6103
6104static TypeTableEntry *analyze_switch_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,4801static TypeTableEntry *analyze_switch_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
6105 TypeTableEntry *expected_type, AstNode *node)4802 TypeTableEntry *expected_type, AstNode *node)
6106{4803{
...@@ -6665,7 +5362,7 @@ static TypeTableEntry *analyze_expression_pointer_only(CodeGen *g, ImportTableEn...@@ -6665,7 +5362,7 @@ static TypeTableEntry *analyze_expression_pointer_only(CodeGen *g, ImportTableEn
6665 return_type = analyze_symbol_expr(g, import, context, expected_type, node, pointer_only);5362 return_type = analyze_symbol_expr(g, import, context, expected_type, node, pointer_only);
6666 break;5363 break;
6667 case NodeTypePrefixOpExpr:5364 case NodeTypePrefixOpExpr:
6668 return_type = analyze_prefix_op_expr(g, import, context, expected_type, node);5365 zig_panic("moved to ir.cpp");
6669 break;5366 break;
6670 case NodeTypeIfBoolExpr:5367 case NodeTypeIfBoolExpr:
6671 return_type = analyze_if_bool_expr(g, import, context, expected_type, node);5368 return_type = analyze_if_bool_expr(g, import, context, expected_type, node);
src/codegen.cpp+2
...@@ -2808,11 +2808,13 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -2808,11 +2808,13 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
2808 case IrInstructionIdCast:2808 case IrInstructionIdCast:
2809 return ir_render_cast(g, executable, (IrInstructionCast *)instruction);2809 return ir_render_cast(g, executable, (IrInstructionCast *)instruction);
2810 case IrInstructionIdCondBr:2810 case IrInstructionIdCondBr:
2811 case IrInstructionIdBr:
2811 case IrInstructionIdSwitchBr:2812 case IrInstructionIdSwitchBr:
2812 case IrInstructionIdPhi:2813 case IrInstructionIdPhi:
2813 case IrInstructionIdStoreVar:2814 case IrInstructionIdStoreVar:
2814 case IrInstructionIdCall:2815 case IrInstructionIdCall:
2815 case IrInstructionIdBuiltinCall:2816 case IrInstructionIdBuiltinCall:
2817 case IrInstructionIdUnOp:
2816 zig_panic("TODO render more IR instructions to LLVM");2818 zig_panic("TODO render more IR instructions to LLVM");
2817 }2819 }
2818 zig_unreachable();2820 zig_unreachable();
src/ir.cpp+1452-35
...@@ -40,6 +40,14 @@ static size_t exec_next_debug_id(IrExecutable *exec) {...@@ -40,6 +40,14 @@ static size_t exec_next_debug_id(IrExecutable *exec) {
40 return result;40 return result;
41}41}
4242
43static IrBasicBlock *ir_build_basic_block(IrBuilder *irb, const char *name_hint) {
44 IrBasicBlock *result = allocate<IrBasicBlock>(1);
45 result->name_hint = name_hint;
46 result->debug_id = exec_next_debug_id(irb->exec);
47 irb->exec->basic_block_list.append(result);
48 return result;
49}
50
43static constexpr IrInstructionId ir_instruction_id(IrInstructionCondBr *) {51static constexpr IrInstructionId ir_instruction_id(IrInstructionCondBr *) {
44 return IrInstructionIdCondBr;52 return IrInstructionIdCondBr;
45}53}
...@@ -52,6 +60,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionPhi *) {...@@ -52,6 +60,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionPhi *) {
52 return IrInstructionIdPhi;60 return IrInstructionIdPhi;
53}61}
5462
63static constexpr IrInstructionId ir_instruction_id(IrInstructionUnOp *) {
64 return IrInstructionIdUnOp;
65}
66
55static constexpr IrInstructionId ir_instruction_id(IrInstructionBinOp *) {67static constexpr IrInstructionId ir_instruction_id(IrInstructionBinOp *) {
56 return IrInstructionIdBinOp;68 return IrInstructionIdBinOp;
57}69}
...@@ -84,6 +96,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCast *) {...@@ -84,6 +96,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCast *) {
84 return IrInstructionIdCast;96 return IrInstructionIdCast;
85}97}
8698
99static constexpr IrInstructionId ir_instruction_id(IrInstructionBr *) {
100 return IrInstructionIdBr;
101}
102
87template<typename T>103template<typename T>
88static T *ir_create_instruction(IrExecutable *exec, AstNode *source_node) {104static T *ir_create_instruction(IrExecutable *exec, AstNode *source_node) {
89 T *special_instruction = allocate<T>(1);105 T *special_instruction = allocate<T>(1);
...@@ -110,6 +126,18 @@ static IrInstruction *ir_build_cast(IrBuilder *irb, AstNode *source_node, IrInst...@@ -110,6 +126,18 @@ static IrInstruction *ir_build_cast(IrBuilder *irb, AstNode *source_node, IrInst
110 return &cast_instruction->base;126 return &cast_instruction->base;
111}127}
112128
129static IrInstruction *ir_build_cond_br(IrBuilder *irb, AstNode *source_node, IrInstruction *condition,
130 IrBasicBlock *then_block, IrBasicBlock *else_block)
131{
132 IrInstructionCondBr *cond_br_instruction = ir_build_instruction<IrInstructionCondBr>(irb, source_node);
133 cond_br_instruction->base.type_entry = irb->codegen->builtin_types.entry_unreachable;
134 cond_br_instruction->base.static_value.ok = true;
135 cond_br_instruction->condition = condition;
136 cond_br_instruction->then_block = then_block;
137 cond_br_instruction->else_block = else_block;
138 return &cond_br_instruction->base;
139}
140
113static IrInstruction *ir_build_return(IrBuilder *irb, AstNode *source_node, IrInstruction *return_value) {141static IrInstruction *ir_build_return(IrBuilder *irb, AstNode *source_node, IrInstruction *return_value) {
114 IrInstructionReturn *return_instruction = ir_build_instruction<IrInstructionReturn>(irb, source_node);142 IrInstructionReturn *return_instruction = ir_build_instruction<IrInstructionReturn>(irb, source_node);
115 return_instruction->base.type_entry = irb->codegen->builtin_types.entry_unreachable;143 return_instruction->base.type_entry = irb->codegen->builtin_types.entry_unreachable;
...@@ -198,6 +226,38 @@ static IrInstruction *ir_build_call(IrBuilder *irb, AstNode *source_node,...@@ -198,6 +226,38 @@ static IrInstruction *ir_build_call(IrBuilder *irb, AstNode *source_node,
198 return &call_instruction->base;226 return &call_instruction->base;
199}227}
200228
229static IrInstruction *ir_build_builtin_call(IrBuilder *irb, AstNode *source_node,
230 BuiltinFnEntry *fn, IrInstruction **args)
231{
232 IrInstructionBuiltinCall *call_instruction = ir_build_instruction<IrInstructionBuiltinCall>(irb, source_node);
233 call_instruction->fn = fn;
234 call_instruction->args = args;
235 return &call_instruction->base;
236}
237
238static IrInstruction *ir_build_phi(IrBuilder *irb, AstNode *source_node,
239 size_t incoming_count, IrBasicBlock **incoming_blocks, IrInstruction **incoming_values)
240{
241 IrInstructionPhi *phi_instruction = ir_build_instruction<IrInstructionPhi>(irb, source_node);
242 phi_instruction->incoming_count = incoming_count;
243 phi_instruction->incoming_blocks = incoming_blocks;
244 phi_instruction->incoming_values = incoming_values;
245 return &phi_instruction->base;
246}
247
248static IrInstruction *ir_build_br(IrBuilder *irb, AstNode *source_node, IrBasicBlock *dest_block) {
249 IrInstructionBr *br_instruction = ir_build_instruction<IrInstructionBr>(irb, source_node);
250 br_instruction->dest_block = dest_block;
251 return &br_instruction->base;
252}
253
254static IrInstruction *ir_build_un_op(IrBuilder *irb, AstNode *source_node, IrUnOp op_id, IrInstruction *value) {
255 IrInstructionUnOp *br_instruction = ir_build_instruction<IrInstructionUnOp>(irb, source_node);
256 br_instruction->op_id = op_id;
257 br_instruction->value = value;
258 return &br_instruction->base;
259}
260
201261
202//static size_t get_conditional_defer_count(BlockContext *inner_block, BlockContext *outer_block) {262//static size_t get_conditional_defer_count(BlockContext *inner_block, BlockContext *outer_block) {
203// size_t result = 0;263// size_t result = 0;
...@@ -246,6 +306,12 @@ static void ir_gen_defers_for_block(IrBuilder *irb, BlockContext *inner_block, B...@@ -246,6 +306,12 @@ static void ir_gen_defers_for_block(IrBuilder *irb, BlockContext *inner_block, B
246// return ir_build_return(irb, source_node, value);306// return ir_build_return(irb, source_node, value);
247//}307//}
248308
309static void ir_set_cursor_at_end(IrBuilder *irb, IrBasicBlock *basic_block) {
310 assert(basic_block);
311
312 irb->current_basic_block = basic_block;
313}
314
249static IrInstruction *ir_gen_block(IrBuilder *irb, AstNode *block_node) {315static IrInstruction *ir_gen_block(IrBuilder *irb, AstNode *block_node) {
250 assert(block_node->type == NodeTypeBlock);316 assert(block_node->type == NodeTypeBlock);
251317
...@@ -433,15 +499,53 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, AstNode *node, bool pointer_...@@ -433,15 +499,53 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, AstNode *node, bool pointer_
433 return irb->codegen->invalid_instruction;499 return irb->codegen->invalid_instruction;
434}500}
435501
436static IrInstruction *ir_gen_fn_call(IrBuilder *irb, AstNode *node) {502static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, AstNode *node) {
437 assert(node->type == NodeTypeFnCallExpr);503 assert(node->type == NodeTypeFnCallExpr);
438504
439 if (node->data.fn_call_expr.is_builtin) {505 AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr;
440 zig_panic("TODO ir gen builtin fn");506 Buf *name = fn_ref_expr->data.symbol_expr.symbol;
507 auto entry = irb->codegen->builtin_fn_table.maybe_get(name);
508
509 if (!entry) {
510 add_node_error(irb->codegen, node,
511 buf_sprintf("invalid builtin function: '%s'", buf_ptr(name)));
512 return irb->codegen->invalid_instruction;
513 }
514
515 BuiltinFnEntry *builtin_fn = entry->value;
516 size_t actual_param_count = node->data.fn_call_expr.params.length;
517
518 if (builtin_fn->param_count != actual_param_count) {
519 add_node_error(irb->codegen, node,
520 buf_sprintf("expected %zu arguments, got %zu",
521 builtin_fn->param_count, actual_param_count));
522 return irb->codegen->invalid_instruction;
523 }
524
525 builtin_fn->ref_count += 1;
526
527 IrInstruction **args = allocate<IrInstruction *>(actual_param_count);
528 for (size_t i = 0; i < actual_param_count; i += 1) {
529 AstNode *arg_node = node->data.fn_call_expr.params.at(i);
530 IrInstruction *arg = ir_gen_node(irb, arg_node, node->block_context);
531 if (arg == irb->codegen->invalid_instruction)
532 return arg;
533 args[i] = arg;
441 }534 }
442535
536 return ir_build_builtin_call(irb, node, builtin_fn, args);
537}
538
539static IrInstruction *ir_gen_fn_call(IrBuilder *irb, AstNode *node) {
540 assert(node->type == NodeTypeFnCallExpr);
541
542 if (node->data.fn_call_expr.is_builtin)
543 return ir_gen_builtin_fn_call(irb, node);
544
443 AstNode *fn_ref_node = node->data.fn_call_expr.fn_ref_expr;545 AstNode *fn_ref_node = node->data.fn_call_expr.fn_ref_expr;
444 IrInstruction *fn = ir_gen_node(irb, fn_ref_node, node->block_context);546 IrInstruction *fn = ir_gen_node(irb, fn_ref_node, node->block_context);
547 if (fn == irb->codegen->invalid_instruction)
548 return fn;
445549
446 size_t arg_count = node->data.fn_call_expr.params.length;550 size_t arg_count = node->data.fn_call_expr.params.length;
447 IrInstruction **args = allocate<IrInstruction*>(arg_count);551 IrInstruction **args = allocate<IrInstruction*>(arg_count);
...@@ -453,9 +557,102 @@ static IrInstruction *ir_gen_fn_call(IrBuilder *irb, AstNode *node) {...@@ -453,9 +557,102 @@ static IrInstruction *ir_gen_fn_call(IrBuilder *irb, AstNode *node) {
453 return ir_build_call(irb, node, fn, arg_count, args);557 return ir_build_call(irb, node, fn, arg_count, args);
454}558}
455559
560static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, AstNode *node) {
561 assert(node->type == NodeTypeIfBoolExpr);
562
563 IrInstruction *condition = ir_gen_node(irb, node->data.if_bool_expr.condition, node->block_context);
564 if (condition == irb->codegen->invalid_instruction)
565 return condition;
566
567 AstNode *then_node = node->data.if_bool_expr.then_block;
568 AstNode *else_node = node->data.if_bool_expr.else_node;
569
570 IrBasicBlock *then_block = ir_build_basic_block(irb, "Then");
571 IrBasicBlock *else_block = ir_build_basic_block(irb, "Else");
572 IrBasicBlock *endif_block = ir_build_basic_block(irb, "EndIf");
573
574 ir_build_cond_br(irb, condition->source_node, condition, then_block, else_block);
575
576 ir_set_cursor_at_end(irb, then_block);
577 IrInstruction *then_expr_result = ir_gen_node(irb, then_node, node->block_context);
578 if (then_expr_result == irb->codegen->invalid_instruction)
579 return then_expr_result;
580 IrBasicBlock *after_then_block = irb->current_basic_block;
581 ir_build_br(irb, node, endif_block);
582
583 ir_set_cursor_at_end(irb, else_block);
584 IrInstruction *else_expr_result;
585 if (else_node) {
586 else_expr_result = ir_gen_node(irb, else_node, node->block_context);
587 if (else_expr_result == irb->codegen->invalid_instruction)
588 return else_expr_result;
589 } else {
590 else_expr_result = ir_build_const_void(irb, node);
591 }
592 IrBasicBlock *after_else_block = irb->current_basic_block;
593 ir_build_br(irb, node, endif_block);
594
595 ir_set_cursor_at_end(irb, endif_block);
596 IrInstruction **incoming_values = allocate<IrInstruction *>(2);
597 incoming_values[0] = then_expr_result;
598 incoming_values[1] = else_expr_result;
599 IrBasicBlock **incoming_blocks = allocate<IrBasicBlock *>(2);
600 incoming_blocks[0] = after_then_block;
601 incoming_blocks[1] = after_else_block;
602
603 return ir_build_phi(irb, node, 2, incoming_blocks, incoming_values);
604}
605
606static IrInstruction *ir_gen_prefix_op_id(IrBuilder *irb, AstNode *node, IrUnOp op_id) {
607 assert(node->type == NodeTypePrefixOpExpr);
608 AstNode *expr_node = node->data.prefix_op_expr.primary_expr;
609
610 IrInstruction *value = ir_gen_node(irb, expr_node, node->block_context);
611 if (value == irb->codegen->invalid_instruction)
612 return value;
613
614 return ir_build_un_op(irb, node, op_id, value);
615}
616
617static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, AstNode *node) {
618 assert(node->type == NodeTypePrefixOpExpr);
619
620 PrefixOp prefix_op = node->data.prefix_op_expr.prefix_op;
621 //AstNode *expr_node = node->data.prefix_op_expr.primary_expr;
622
623 switch (prefix_op) {
624 case PrefixOpInvalid:
625 zig_unreachable();
626 case PrefixOpBoolNot:
627 return ir_gen_prefix_op_id(irb, node, IrUnOpBoolNot);
628 case PrefixOpBinNot:
629 return ir_gen_prefix_op_id(irb, node, IrUnOpBinNot);
630 case PrefixOpNegation:
631 return ir_gen_prefix_op_id(irb, node, IrUnOpNegation);
632 case PrefixOpNegationWrap:
633 return ir_gen_prefix_op_id(irb, node, IrUnOpNegationWrap);
634 case PrefixOpAddressOf:
635 return ir_gen_prefix_op_id(irb, node, IrUnOpAddressOf);
636 case PrefixOpConstAddressOf:
637 return ir_gen_prefix_op_id(irb, node, IrUnOpConstAddressOf);
638 case PrefixOpDereference:
639 return ir_gen_prefix_op_id(irb, node, IrUnOpDereference);
640 case PrefixOpMaybe:
641 return ir_gen_prefix_op_id(irb, node, IrUnOpMaybe);
642 case PrefixOpError:
643 return ir_gen_prefix_op_id(irb, node, IrUnOpError);
644 case PrefixOpUnwrapError:
645 return ir_gen_prefix_op_id(irb, node, IrUnOpUnwrapError);
646 case PrefixOpUnwrapMaybe:
647 return ir_gen_prefix_op_id(irb, node, IrUnOpUnwrapMaybe);
648 }
649 zig_unreachable();
650}
651
456static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockContext *block_context,652static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockContext *block_context,
457 bool pointer_only)653 bool pointer_only)
458{654{
655 assert(block_context);
459 node->block_context = block_context;656 node->block_context = block_context;
460657
461 switch (node->type) {658 switch (node->type) {
...@@ -469,15 +666,17 @@ static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockCont...@@ -469,15 +666,17 @@ static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockCont
469 return ir_gen_symbol(irb, node, pointer_only);666 return ir_gen_symbol(irb, node, pointer_only);
470 case NodeTypeFnCallExpr:667 case NodeTypeFnCallExpr:
471 return ir_gen_fn_call(irb, node);668 return ir_gen_fn_call(irb, node);
669 case NodeTypeIfBoolExpr:
670 return ir_gen_if_bool_expr(irb, node);
671 case NodeTypePrefixOpExpr:
672 return ir_gen_prefix_op_expr(irb, node);
472 case NodeTypeUnwrapErrorExpr:673 case NodeTypeUnwrapErrorExpr:
473 case NodeTypeReturnExpr:674 case NodeTypeReturnExpr:
474 case NodeTypeDefer:675 case NodeTypeDefer:
475 case NodeTypeVariableDeclaration:676 case NodeTypeVariableDeclaration:
476 case NodeTypePrefixOpExpr:
477 case NodeTypeArrayAccessExpr:677 case NodeTypeArrayAccessExpr:
478 case NodeTypeSliceExpr:678 case NodeTypeSliceExpr:
479 case NodeTypeFieldAccessExpr:679 case NodeTypeFieldAccessExpr:
480 case NodeTypeIfBoolExpr:
481 case NodeTypeIfVarExpr:680 case NodeTypeIfVarExpr:
482 case NodeTypeWhileExpr:681 case NodeTypeWhileExpr:
483 case NodeTypeForExpr:682 case NodeTypeForExpr:
...@@ -533,8 +732,7 @@ static IrInstruction *ir_gen_add_return(CodeGen *g, AstNode *node, BlockContext...@@ -533,8 +732,7 @@ static IrInstruction *ir_gen_add_return(CodeGen *g, AstNode *node, BlockContext
533 irb->codegen = g;732 irb->codegen = g;
534 irb->exec = ir_executable;733 irb->exec = ir_executable;
535734
536 irb->current_basic_block = allocate<IrBasicBlock>(1);735 irb->current_basic_block = ir_build_basic_block(irb, "Entry");
537 irb->exec->basic_block_list.append(irb->current_basic_block);
538736
539 IrInstruction *result = ir_gen_node_extra(irb, node, scope, pointer_only);737 IrInstruction *result = ir_gen_node_extra(irb, node, scope, pointer_only);
540 assert(result);738 assert(result);
...@@ -648,7 +846,7 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc...@@ -648,7 +846,7 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc
648846
649 const char *num_lit_str = (const_val->data.x_bignum.kind == BigNumKindFloat) ? "float" : "integer";847 const char *num_lit_str = (const_val->data.x_bignum.kind == BigNumKindFloat) ? "float" : "integer";
650848
651 add_node_error(ira->old_irb.codegen, instruction->source_node,849 add_node_error(ira->codegen, instruction->source_node,
652 buf_sprintf("%s value %s cannot be implicitly casted to type '%s'",850 buf_sprintf("%s value %s cannot be implicitly casted to type '%s'",
653 num_lit_str,851 num_lit_str,
654 buf_ptr(bignum_to_buf(&const_val->data.x_bignum)),852 buf_ptr(bignum_to_buf(&const_val->data.x_bignum)),
...@@ -662,7 +860,7 @@ static TypeTableEntry *ir_determine_peer_types(IrAnalyze *ira, IrInstruction *pa...@@ -662,7 +860,7 @@ static TypeTableEntry *ir_determine_peer_types(IrAnalyze *ira, IrInstruction *pa
662 assert(instruction_count >= 1);860 assert(instruction_count >= 1);
663 IrInstruction *prev_inst = instructions[0];861 IrInstruction *prev_inst = instructions[0];
664 if (prev_inst->type_entry->id == TypeTableEntryIdInvalid) {862 if (prev_inst->type_entry->id == TypeTableEntryIdInvalid) {
665 return ira->old_irb.codegen->builtin_types.entry_invalid;863 return ira->codegen->builtin_types.entry_invalid;
666 }864 }
667 for (size_t i = 1; i < instruction_count; i += 1) {865 for (size_t i = 1; i < instruction_count; i += 1) {
668 IrInstruction *cur_inst = instructions[i];866 IrInstruction *cur_inst = instructions[i];
...@@ -709,7 +907,7 @@ static TypeTableEntry *ir_determine_peer_types(IrAnalyze *ira, IrInstruction *pa...@@ -709,7 +907,7 @@ static TypeTableEntry *ir_determine_peer_types(IrAnalyze *ira, IrInstruction *pa
709 prev_inst = cur_inst;907 prev_inst = cur_inst;
710 continue;908 continue;
711 } else {909 } else {
712 return ira->old_irb.codegen->builtin_types.entry_invalid;910 return ira->codegen->builtin_types.entry_invalid;
713 }911 }
714 } else if (cur_type->id == TypeTableEntryIdNumLitInt ||912 } else if (cur_type->id == TypeTableEntryIdNumLitInt ||
715 cur_type->id == TypeTableEntryIdNumLitFloat)913 cur_type->id == TypeTableEntryIdNumLitFloat)
...@@ -717,14 +915,14 @@ static TypeTableEntry *ir_determine_peer_types(IrAnalyze *ira, IrInstruction *pa...@@ -717,14 +915,14 @@ static TypeTableEntry *ir_determine_peer_types(IrAnalyze *ira, IrInstruction *pa
717 if (ir_num_lit_fits_in_other_type(ira, cur_inst, prev_type)) {915 if (ir_num_lit_fits_in_other_type(ira, cur_inst, prev_type)) {
718 continue;916 continue;
719 } else {917 } else {
720 return ira->old_irb.codegen->builtin_types.entry_invalid;918 return ira->codegen->builtin_types.entry_invalid;
721 }919 }
722 } else {920 } else {
723 add_node_error(ira->old_irb.codegen, parent_instruction->source_node,921 add_node_error(ira->codegen, parent_instruction->source_node,
724 buf_sprintf("incompatible types: '%s' and '%s'",922 buf_sprintf("incompatible types: '%s' and '%s'",
725 buf_ptr(&prev_type->name), buf_ptr(&cur_type->name)));923 buf_ptr(&prev_type->name), buf_ptr(&cur_type->name)));
726924
727 return ira->old_irb.codegen->builtin_types.entry_invalid;925 return ira->codegen->builtin_types.entry_invalid;
728 }926 }
729 }927 }
730 return prev_inst->type_entry;928 return prev_inst->type_entry;
...@@ -1119,7 +1317,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -1119,7 +1317,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
11191317
1120static IrInstruction *ir_get_casted_value(IrAnalyze *ira, IrInstruction *value, TypeTableEntry *expected_type) {1318static IrInstruction *ir_get_casted_value(IrAnalyze *ira, IrInstruction *value, TypeTableEntry *expected_type) {
1121 assert(value);1319 assert(value);
1122 assert(value != ira->old_irb.codegen->invalid_instruction);1320 assert(value != ira->codegen->invalid_instruction);
1123 assert(!expected_type || expected_type->id != TypeTableEntryIdInvalid);1321 assert(!expected_type || expected_type->id != TypeTableEntryIdInvalid);
1124 assert(value->type_entry);1322 assert(value->type_entry);
1125 assert(value->type_entry->id != TypeTableEntryIdInvalid);1323 assert(value->type_entry->id != TypeTableEntryIdInvalid);
...@@ -1133,11 +1331,11 @@ static IrInstruction *ir_get_casted_value(IrAnalyze *ira, IrInstruction *value,...@@ -1133,11 +1331,11 @@ static IrInstruction *ir_get_casted_value(IrAnalyze *ira, IrInstruction *value,
1133 ImplicitCastMatchResult result = ir_types_match_with_implicit_cast(ira, expected_type, value->type_entry, value);1331 ImplicitCastMatchResult result = ir_types_match_with_implicit_cast(ira, expected_type, value->type_entry, value);
1134 switch (result) {1332 switch (result) {
1135 case ImplicitCastMatchResultNo:1333 case ImplicitCastMatchResultNo:
1136 add_node_error(ira->old_irb.codegen, first_executing_node(value->source_node),1334 add_node_error(ira->codegen, first_executing_node(value->source_node),
1137 buf_sprintf("expected type '%s', got '%s'",1335 buf_sprintf("expected type '%s', got '%s'",
1138 buf_ptr(&expected_type->name),1336 buf_ptr(&expected_type->name),
1139 buf_ptr(&value->type_entry->name)));1337 buf_ptr(&value->type_entry->name)));
1140 return ira->old_irb.codegen->invalid_instruction;1338 return ira->codegen->invalid_instruction;
11411339
1142 case ImplicitCastMatchResultYes:1340 case ImplicitCastMatchResultYes:
1143 {1341 {
...@@ -1146,7 +1344,7 @@ static IrInstruction *ir_get_casted_value(IrAnalyze *ira, IrInstruction *value,...@@ -1146,7 +1344,7 @@ static IrInstruction *ir_get_casted_value(IrAnalyze *ira, IrInstruction *value,
1146 return cast_instruction;1344 return cast_instruction;
1147 }1345 }
1148 case ImplicitCastMatchResultReportedError:1346 case ImplicitCastMatchResultReportedError:
1149 return ira->old_irb.codegen->invalid_instruction;1347 return ira->codegen->invalid_instruction;
1150 }1348 }
11511349
1152 zig_unreachable();1350 zig_unreachable();
...@@ -1182,15 +1380,15 @@ static TypeTableEntry *ir_analyze_bin_op_bool(IrAnalyze *ira, IrInstructionBinOp...@@ -1182,15 +1380,15 @@ static TypeTableEntry *ir_analyze_bin_op_bool(IrAnalyze *ira, IrInstructionBinOp
1182 IrInstruction *op1 = bin_op_instruction->op1;1380 IrInstruction *op1 = bin_op_instruction->op1;
1183 IrInstruction *op2 = bin_op_instruction->op2;1381 IrInstruction *op2 = bin_op_instruction->op2;
11841382
1185 TypeTableEntry *bool_type = ira->old_irb.codegen->builtin_types.entry_bool;1383 TypeTableEntry *bool_type = ira->codegen->builtin_types.entry_bool;
11861384
1187 IrInstruction *casted_op1 = ir_get_casted_value(ira, op1->other, bool_type);1385 IrInstruction *casted_op1 = ir_get_casted_value(ira, op1->other, bool_type);
1188 if (casted_op1 == ira->old_irb.codegen->invalid_instruction)1386 if (casted_op1 == ira->codegen->invalid_instruction)
1189 return ira->old_irb.codegen->builtin_types.entry_invalid;1387 return ira->codegen->builtin_types.entry_invalid;
11901388
1191 IrInstruction *casted_op2 = ir_get_casted_value(ira, op2->other, bool_type);1389 IrInstruction *casted_op2 = ir_get_casted_value(ira, op2->other, bool_type);
1192 if (casted_op2 == ira->old_irb.codegen->invalid_instruction)1390 if (casted_op2 == ira->codegen->invalid_instruction)
1193 return ira->old_irb.codegen->builtin_types.entry_invalid;1391 return ira->codegen->builtin_types.entry_invalid;
11941392
1195 ConstExprValue *op1_val = &casted_op1->static_value;1393 ConstExprValue *op1_val = &casted_op1->static_value;
1196 ConstExprValue *op2_val = &casted_op2->static_value;1394 ConstExprValue *op2_val = &casted_op2->static_value;
...@@ -1232,7 +1430,7 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp...@@ -1232,7 +1430,7 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp
1232 AstNode *source_node = bin_op_instruction->base.source_node;1430 AstNode *source_node = bin_op_instruction->base.source_node;
1233 switch (resolved_type->id) {1431 switch (resolved_type->id) {
1234 case TypeTableEntryIdInvalid:1432 case TypeTableEntryIdInvalid:
1235 return ira->old_irb.codegen->builtin_types.entry_invalid;1433 return ira->codegen->builtin_types.entry_invalid;
12361434
1237 case TypeTableEntryIdNumLitFloat:1435 case TypeTableEntryIdNumLitFloat:
1238 case TypeTableEntryIdNumLitInt:1436 case TypeTableEntryIdNumLitInt:
...@@ -1251,17 +1449,17 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp...@@ -1251,17 +1449,17 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp
1251 case TypeTableEntryIdBlock:1449 case TypeTableEntryIdBlock:
1252 case TypeTableEntryIdGenericFn:1450 case TypeTableEntryIdGenericFn:
1253 if (!is_equality_cmp) {1451 if (!is_equality_cmp) {
1254 add_node_error(ira->old_irb.codegen, source_node,1452 add_node_error(ira->codegen, source_node,
1255 buf_sprintf("operator not allowed for type '%s'", buf_ptr(&resolved_type->name)));1453 buf_sprintf("operator not allowed for type '%s'", buf_ptr(&resolved_type->name)));
1256 return ira->old_irb.codegen->builtin_types.entry_invalid;1454 return ira->codegen->builtin_types.entry_invalid;
1257 }1455 }
1258 break;1456 break;
12591457
1260 case TypeTableEntryIdEnum:1458 case TypeTableEntryIdEnum:
1261 if (!is_equality_cmp || resolved_type->data.enumeration.gen_field_count != 0) {1459 if (!is_equality_cmp || resolved_type->data.enumeration.gen_field_count != 0) {
1262 add_node_error(ira->old_irb.codegen, source_node,1460 add_node_error(ira->codegen, source_node,
1263 buf_sprintf("operator not allowed for type '%s'", buf_ptr(&resolved_type->name)));1461 buf_sprintf("operator not allowed for type '%s'", buf_ptr(&resolved_type->name)));
1264 return ira->old_irb.codegen->builtin_types.entry_invalid;1462 return ira->codegen->builtin_types.entry_invalid;
1265 }1463 }
1266 break;1464 break;
12671465
...@@ -1273,9 +1471,9 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp...@@ -1273,9 +1471,9 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp
1273 case TypeTableEntryIdMaybe:1471 case TypeTableEntryIdMaybe:
1274 case TypeTableEntryIdErrorUnion:1472 case TypeTableEntryIdErrorUnion:
1275 case TypeTableEntryIdUnion:1473 case TypeTableEntryIdUnion:
1276 add_node_error(ira->old_irb.codegen, source_node,1474 add_node_error(ira->codegen, source_node,
1277 buf_sprintf("operator not allowed for type '%s'", buf_ptr(&resolved_type->name)));1475 buf_sprintf("operator not allowed for type '%s'", buf_ptr(&resolved_type->name)));
1278 return ira->old_irb.codegen->builtin_types.entry_invalid;1476 return ira->codegen->builtin_types.entry_invalid;
12791477
1280 case TypeTableEntryIdVar:1478 case TypeTableEntryIdVar:
1281 zig_unreachable();1479 zig_unreachable();
...@@ -1286,7 +1484,7 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp...@@ -1286,7 +1484,7 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp
1286 ir_link_new(ir_build_bin_op(&ira->new_irb, bin_op_instruction->base.source_node,1484 ir_link_new(ir_build_bin_op(&ira->new_irb, bin_op_instruction->base.source_node,
1287 op_id, op1->other, op2->other), &bin_op_instruction->base);1485 op_id, op1->other, op2->other), &bin_op_instruction->base);
12881486
1289 return ira->old_irb.codegen->builtin_types.entry_bool;1487 return ira->codegen->builtin_types.entry_bool;
1290}1488}
12911489
1292static uint64_t max_unsigned_val(TypeTableEntry *type_entry) {1490static uint64_t max_unsigned_val(TypeTableEntry *type_entry) {
...@@ -1408,11 +1606,11 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp...@@ -1408,11 +1606,11 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
1408 // float1606 // float
1409 } else {1607 } else {
1410 AstNode *source_node = bin_op_instruction->base.source_node;1608 AstNode *source_node = bin_op_instruction->base.source_node;
1411 add_node_error(ira->old_irb.codegen, source_node,1609 add_node_error(ira->codegen, source_node,
1412 buf_sprintf("invalid operands to binary expression: '%s' and '%s'",1610 buf_sprintf("invalid operands to binary expression: '%s' and '%s'",
1413 buf_ptr(&op1->type_entry->name),1611 buf_ptr(&op1->type_entry->name),
1414 buf_ptr(&op2->type_entry->name)));1612 buf_ptr(&op2->type_entry->name)));
1415 return ira->old_irb.codegen->builtin_types.entry_invalid;1613 return ira->codegen->builtin_types.entry_invalid;
1416 }1614 }
14171615
1418 if (op1->static_value.ok && op2->static_value.ok) {1616 if (op1->static_value.ok && op2->static_value.ok) {
...@@ -1525,6 +1723,1224 @@ static TypeTableEntry *ir_analyze_instruction_call(IrAnalyze *ira, IrInstruction...@@ -1525,6 +1723,1224 @@ static TypeTableEntry *ir_analyze_instruction_call(IrAnalyze *ira, IrInstruction
1525 }1723 }
1526}1724}
15271725
1726static TypeTableEntry *ir_analyze_unary_bool_not(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) {
1727 TypeTableEntry *bool_type = ira->codegen->builtin_types.entry_bool;
1728
1729 IrInstruction *casted_value = ir_get_casted_value(ira, un_op_instruction->value, bool_type);
1730 if (casted_value == ira->codegen->invalid_instruction)
1731 return ira->codegen->builtin_types.entry_invalid;
1732
1733 ConstExprValue *operand_val = &casted_value->static_value;
1734 if (operand_val->ok) {
1735 ConstExprValue *result_val = &un_op_instruction->base.static_value;
1736 result_val->ok = true;
1737 result_val->depends_on_compile_var = operand_val->depends_on_compile_var;
1738 result_val->data.x_bool = !operand_val->data.x_bool;
1739 return bool_type;
1740 }
1741
1742 IrInstruction *new_instruction = ir_build_un_op(&ira->new_irb, un_op_instruction->base.source_node,
1743 IrUnOpBoolNot, casted_value);
1744 ir_link_new(new_instruction, &un_op_instruction->base);
1745
1746 return bool_type;
1747}
1748
1749static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) {
1750 IrUnOp op_id = un_op_instruction->op_id;
1751 switch (op_id) {
1752 case IrUnOpInvalid:
1753 zig_unreachable();
1754 case IrUnOpBoolNot:
1755 return ir_analyze_unary_bool_not(ira, un_op_instruction);
1756 zig_panic("TODO analyze PrefixOpBoolNot");
1757 case IrUnOpBinNot:
1758 zig_panic("TODO analyze PrefixOpBinNot");
1759 //{
1760 // TypeTableEntry *expr_type = analyze_expression(g, import, context, expected_type,
1761 // *expr_node);
1762 // if (expr_type->id == TypeTableEntryIdInvalid) {
1763 // return expr_type;
1764 // } else if (expr_type->id == TypeTableEntryIdInt) {
1765 // return expr_type;
1766 // } else {
1767 // add_node_error(g, node, buf_sprintf("unable to perform binary not operation on type '%s'",
1768 // buf_ptr(&expr_type->name)));
1769 // return g->builtin_types.entry_invalid;
1770 // }
1771 // // TODO const expr eval
1772 //}
1773 case IrUnOpNegation:
1774 case IrUnOpNegationWrap:
1775 zig_panic("TODO analyze PrefixOpNegation[Wrap]");
1776 //{
1777 // TypeTableEntry *expr_type = analyze_expression(g, import, context, nullptr, *expr_node);
1778 // if (expr_type->id == TypeTableEntryIdInvalid) {
1779 // return expr_type;
1780 // } else if ((expr_type->id == TypeTableEntryIdInt &&
1781 // expr_type->data.integral.is_signed) ||
1782 // expr_type->id == TypeTableEntryIdNumLitInt ||
1783 // ((expr_type->id == TypeTableEntryIdFloat ||
1784 // expr_type->id == TypeTableEntryIdNumLitFloat) &&
1785 // prefix_op != PrefixOpNegationWrap))
1786 // {
1787 // ConstExprValue *target_const_val = &get_resolved_expr(*expr_node)->const_val;
1788 // if (!target_const_val->ok) {
1789 // return expr_type;
1790 // }
1791 // ConstExprValue *const_val = &get_resolved_expr(node)->const_val;
1792 // const_val->ok = true;
1793 // const_val->depends_on_compile_var = target_const_val->depends_on_compile_var;
1794 // bignum_negate(&const_val->data.x_bignum, &target_const_val->data.x_bignum);
1795 // if (expr_type->id == TypeTableEntryIdFloat ||
1796 // expr_type->id == TypeTableEntryIdNumLitFloat ||
1797 // expr_type->id == TypeTableEntryIdNumLitInt)
1798 // {
1799 // return expr_type;
1800 // }
1801
1802 // bool overflow = !bignum_fits_in_bits(&const_val->data.x_bignum,
1803 // expr_type->data.integral.bit_count, expr_type->data.integral.is_signed);
1804 // if (prefix_op == PrefixOpNegationWrap) {
1805 // if (overflow) {
1806 // const_val->data.x_bignum.is_negative = true;
1807 // }
1808 // } else if (overflow) {
1809 // add_node_error(g, *expr_node, buf_sprintf("negation caused overflow"));
1810 // return g->builtin_types.entry_invalid;
1811 // }
1812 // return expr_type;
1813 // } else {
1814 // const char *fmt = (prefix_op == PrefixOpNegationWrap) ?
1815 // "invalid wrapping negation type: '%s'" : "invalid negation type: '%s'";
1816 // add_node_error(g, node, buf_sprintf(fmt, buf_ptr(&expr_type->name)));
1817 // return g->builtin_types.entry_invalid;
1818 // }
1819 //}
1820 case IrUnOpAddressOf:
1821 case IrUnOpConstAddressOf:
1822 zig_panic("TODO analyze PrefixOpAddressOf and PrefixOpConstAddressOf");
1823 //{
1824 // bool is_const = (prefix_op == PrefixOpConstAddressOf);
1825
1826 // TypeTableEntry *child_type = analyze_lvalue(g, import, context,
1827 // *expr_node, LValPurposeAddressOf, is_const);
1828
1829 // if (child_type->id == TypeTableEntryIdInvalid) {
1830 // return g->builtin_types.entry_invalid;
1831 // } else if (child_type->id == TypeTableEntryIdMetaType) {
1832 // TypeTableEntry *meta_type = analyze_type_expr_pointer_only(g, import, context,
1833 // *expr_node, true);
1834 // if (meta_type->id == TypeTableEntryIdInvalid) {
1835 // return g->builtin_types.entry_invalid;
1836 // } else if (meta_type->id == TypeTableEntryIdUnreachable) {
1837 // add_node_error(g, node, buf_create_from_str("pointer to unreachable not allowed"));
1838 // return g->builtin_types.entry_invalid;
1839 // } else {
1840 // return resolve_expr_const_val_as_type(g, node,
1841 // get_pointer_to_type(g, meta_type, is_const), false);
1842 // }
1843 // } else if (child_type->id == TypeTableEntryIdNumLitInt ||
1844 // child_type->id == TypeTableEntryIdNumLitFloat)
1845 // {
1846 // add_node_error(g, *expr_node,
1847 // buf_sprintf("unable to get address of type '%s'", buf_ptr(&child_type->name)));
1848 // return g->builtin_types.entry_invalid;
1849 // } else {
1850 // return get_pointer_to_type(g, child_type, is_const);
1851 // }
1852 //}
1853 case IrUnOpDereference:
1854 zig_panic("TODO analyze PrefixOpDereference");
1855 //{
1856 // TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, *expr_node);
1857 // if (type_entry->id == TypeTableEntryIdInvalid) {
1858 // return type_entry;
1859 // } else if (type_entry->id == TypeTableEntryIdPointer) {
1860 // return type_entry->data.pointer.child_type;
1861 // } else {
1862 // add_node_error(g, *expr_node,
1863 // buf_sprintf("indirection requires pointer operand ('%s' invalid)",
1864 // buf_ptr(&type_entry->name)));
1865 // return g->builtin_types.entry_invalid;
1866 // }
1867 //}
1868 case IrUnOpMaybe:
1869 zig_panic("TODO analyze PrefixOpMaybe");
1870 //{
1871 // TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, *expr_node);
1872
1873 // if (type_entry->id == TypeTableEntryIdInvalid) {
1874 // return type_entry;
1875 // } else if (type_entry->id == TypeTableEntryIdMetaType) {
1876 // TypeTableEntry *meta_type = resolve_type(g, *expr_node);
1877 // if (meta_type->id == TypeTableEntryIdInvalid) {
1878 // return g->builtin_types.entry_invalid;
1879 // } else if (meta_type->id == TypeTableEntryIdUnreachable) {
1880 // add_node_error(g, node, buf_create_from_str("unable to wrap unreachable in maybe type"));
1881 // return g->builtin_types.entry_invalid;
1882 // } else {
1883 // return resolve_expr_const_val_as_type(g, node, get_maybe_type(g, meta_type), false);
1884 // }
1885 // } else if (type_entry->id == TypeTableEntryIdUnreachable) {
1886 // add_node_error(g, *expr_node, buf_sprintf("unable to wrap unreachable in maybe type"));
1887 // return g->builtin_types.entry_invalid;
1888 // } else {
1889 // ConstExprValue *target_const_val = &get_resolved_expr(*expr_node)->const_val;
1890 // TypeTableEntry *maybe_type = get_maybe_type(g, type_entry);
1891 // if (!target_const_val->ok) {
1892 // return maybe_type;
1893 // }
1894 // return resolve_expr_const_val_as_non_null(g, node, maybe_type, target_const_val);
1895 // }
1896 //}
1897 case IrUnOpError:
1898 zig_panic("TODO analyze PrefixOpError");
1899 //{
1900 // TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, *expr_node);
1901
1902 // if (type_entry->id == TypeTableEntryIdInvalid) {
1903 // return type_entry;
1904 // } else if (type_entry->id == TypeTableEntryIdMetaType) {
1905 // TypeTableEntry *meta_type = resolve_type(g, *expr_node);
1906 // if (meta_type->id == TypeTableEntryIdInvalid) {
1907 // return meta_type;
1908 // } else if (meta_type->id == TypeTableEntryIdUnreachable) {
1909 // add_node_error(g, node, buf_create_from_str("unable to wrap unreachable in error type"));
1910 // return g->builtin_types.entry_invalid;
1911 // } else {
1912 // return resolve_expr_const_val_as_type(g, node, get_error_type(g, meta_type), false);
1913 // }
1914 // } else if (type_entry->id == TypeTableEntryIdUnreachable) {
1915 // add_node_error(g, *expr_node, buf_sprintf("unable to wrap unreachable in error type"));
1916 // return g->builtin_types.entry_invalid;
1917 // } else {
1918 // // TODO eval const expr
1919 // return get_error_type(g, type_entry);
1920 // }
1921
1922 //}
1923 case IrUnOpUnwrapError:
1924 zig_panic("TODO analyze PrefixOpUnwrapError");
1925 //{
1926 // TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, *expr_node);
1927
1928 // if (type_entry->id == TypeTableEntryIdInvalid) {
1929 // return type_entry;
1930 // } else if (type_entry->id == TypeTableEntryIdErrorUnion) {
1931 // return type_entry->data.error.child_type;
1932 // } else {
1933 // add_node_error(g, *expr_node,
1934 // buf_sprintf("expected error type, got '%s'", buf_ptr(&type_entry->name)));
1935 // return g->builtin_types.entry_invalid;
1936 // }
1937 //}
1938 case IrUnOpUnwrapMaybe:
1939 zig_panic("TODO analyze PrefixOpUnwrapMaybe");
1940 //{
1941 // TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, *expr_node);
1942
1943 // if (type_entry->id == TypeTableEntryIdInvalid) {
1944 // return type_entry;
1945 // } else if (type_entry->id == TypeTableEntryIdMaybe) {
1946 // return type_entry->data.maybe.child_type;
1947 // } else {
1948 // add_node_error(g, *expr_node,
1949 // buf_sprintf("expected maybe type, got '%s'", buf_ptr(&type_entry->name)));
1950 // return g->builtin_types.entry_invalid;
1951 // }
1952 //}
1953 case IrUnOpErrorReturn:
1954 zig_panic("TODO analyze IrUnOpErrorReturn");
1955 case IrUnOpMaybeReturn:
1956 zig_panic("TODO analyze IrUnOpMaybeReturn");
1957 }
1958 zig_unreachable();
1959}
1960
1961//static TypeTableEntry *analyze_min_max_value(CodeGen *g, ImportTableEntry *import, BlockContext *context,
1962// AstNode *node, const char *err_format, bool is_max)
1963//{
1964// assert(node->type == NodeTypeFnCallExpr);
1965// assert(node->data.fn_call_expr.params.length == 1);
1966//
1967// AstNode *type_node = node->data.fn_call_expr.params.at(0);
1968// TypeTableEntry *type_entry = analyze_type_expr(g, import, context, type_node);
1969//
1970// if (type_entry->id == TypeTableEntryIdInvalid) {
1971// return g->builtin_types.entry_invalid;
1972// } else if (type_entry->id == TypeTableEntryIdInt) {
1973// eval_min_max_value(g, type_entry, &get_resolved_expr(node)->const_val, is_max);
1974// return g->builtin_types.entry_num_lit_int;
1975// } else if (type_entry->id == TypeTableEntryIdFloat) {
1976// eval_min_max_value(g, type_entry, &get_resolved_expr(node)->const_val, is_max);
1977// return g->builtin_types.entry_num_lit_float;
1978// } else if (type_entry->id == TypeTableEntryIdBool) {
1979// eval_min_max_value(g, type_entry, &get_resolved_expr(node)->const_val, is_max);
1980// return type_entry;
1981// } else {
1982// add_node_error(g, node,
1983// buf_sprintf(err_format, buf_ptr(&type_entry->name)));
1984// return g->builtin_types.entry_invalid;
1985// }
1986//}
1987
1988//static TypeTableEntry *analyze_import(CodeGen *g, ImportTableEntry *import, BlockContext *context,
1989// AstNode *node)
1990//{
1991// assert(node->type == NodeTypeFnCallExpr);
1992//
1993// if (context->fn_entry) {
1994// add_node_error(g, node, buf_sprintf("@import invalid inside function bodies"));
1995// return g->builtin_types.entry_invalid;
1996// }
1997//
1998// AstNode *first_param_node = node->data.fn_call_expr.params.at(0);
1999// Buf *import_target_str = resolve_const_expr_str(g, import, context, first_param_node->parent_field);
2000// if (!import_target_str) {
2001// return g->builtin_types.entry_invalid;
2002// }
2003//
2004// Buf *import_target_path;
2005// Buf *search_dir;
2006// assert(import->package);
2007// PackageTableEntry *target_package;
2008// auto package_entry = import->package->package_table.maybe_get(import_target_str);
2009// if (package_entry) {
2010// target_package = package_entry->value;
2011// import_target_path = &target_package->root_src_path;
2012// search_dir = &target_package->root_src_dir;
2013// } else {
2014// // try it as a filename
2015// target_package = import->package;
2016// import_target_path = import_target_str;
2017// search_dir = &import->package->root_src_dir;
2018// }
2019//
2020// Buf full_path = BUF_INIT;
2021// os_path_join(search_dir, import_target_path, &full_path);
2022//
2023// Buf *import_code = buf_alloc();
2024// Buf *abs_full_path = buf_alloc();
2025// int err;
2026// if ((err = os_path_real(&full_path, abs_full_path))) {
2027// if (err == ErrorFileNotFound) {
2028// add_node_error(g, node,
2029// buf_sprintf("unable to find '%s'", buf_ptr(import_target_path)));
2030// return g->builtin_types.entry_invalid;
2031// } else {
2032// g->error_during_imports = true;
2033// add_node_error(g, node,
2034// buf_sprintf("unable to open '%s': %s", buf_ptr(&full_path), err_str(err)));
2035// return g->builtin_types.entry_invalid;
2036// }
2037// }
2038//
2039// auto import_entry = g->import_table.maybe_get(abs_full_path);
2040// if (import_entry) {
2041// return resolve_expr_const_val_as_import(g, node, import_entry->value);
2042// }
2043//
2044// if ((err = os_fetch_file_path(abs_full_path, import_code))) {
2045// if (err == ErrorFileNotFound) {
2046// add_node_error(g, node,
2047// buf_sprintf("unable to find '%s'", buf_ptr(import_target_path)));
2048// return g->builtin_types.entry_invalid;
2049// } else {
2050// add_node_error(g, node,
2051// buf_sprintf("unable to open '%s': %s", buf_ptr(&full_path), err_str(err)));
2052// return g->builtin_types.entry_invalid;
2053// }
2054// }
2055// ImportTableEntry *target_import = add_source_file(g, target_package,
2056// abs_full_path, search_dir, import_target_path, import_code);
2057//
2058// scan_decls(g, target_import, target_import->block_context, target_import->root);
2059//
2060// return resolve_expr_const_val_as_import(g, node, target_import);
2061//}
2062//
2063//static TypeTableEntry *analyze_c_import(CodeGen *g, ImportTableEntry *parent_import,
2064// BlockContext *parent_context, AstNode *node)
2065//{
2066// assert(node->type == NodeTypeFnCallExpr);
2067//
2068// if (parent_context->fn_entry) {
2069// add_node_error(g, node, buf_sprintf("@c_import invalid inside function bodies"));
2070// return g->builtin_types.entry_invalid;
2071// }
2072//
2073// AstNode *block_node = node->data.fn_call_expr.params.at(0);
2074//
2075// BlockContext *child_context = new_block_context(node, parent_context);
2076// child_context->c_import_buf = buf_alloc();
2077//
2078// TypeTableEntry *resolved_type = analyze_expression(g, parent_import, child_context,
2079// g->builtin_types.entry_void, block_node);
2080//
2081// if (resolved_type->id == TypeTableEntryIdInvalid) {
2082// return resolved_type;
2083// }
2084//
2085// find_libc_include_path(g);
2086//
2087// ImportTableEntry *child_import = allocate<ImportTableEntry>(1);
2088// child_import->c_import_node = node;
2089//
2090// ZigList<ErrorMsg *> errors = {0};
2091//
2092// int err;
2093// if ((err = parse_h_buf(child_import, &errors, child_context->c_import_buf, g, node))) {
2094// zig_panic("unable to parse h file: %s\n", err_str(err));
2095// }
2096//
2097// if (errors.length > 0) {
2098// ErrorMsg *parent_err_msg = add_node_error(g, node, buf_sprintf("C import failed"));
2099// for (size_t i = 0; i < errors.length; i += 1) {
2100// ErrorMsg *err_msg = errors.at(i);
2101// err_msg_add_note(parent_err_msg, err_msg);
2102// }
2103//
2104// return g->builtin_types.entry_invalid;
2105// }
2106//
2107// if (g->verbose) {
2108// fprintf(stderr, "\nc_import:\n");
2109// fprintf(stderr, "-----------\n");
2110// ast_render(stderr, child_import->root, 4);
2111// }
2112//
2113// child_import->di_file = parent_import->di_file;
2114// child_import->block_context = new_block_context(child_import->root, nullptr);
2115//
2116// scan_decls(g, child_import, child_import->block_context, child_import->root);
2117// return resolve_expr_const_val_as_import(g, node, child_import);
2118//}
2119//
2120//static TypeTableEntry *analyze_err_name(CodeGen *g, ImportTableEntry *import,
2121// BlockContext *context, AstNode *node)
2122//{
2123// assert(node->type == NodeTypeFnCallExpr);
2124//
2125// AstNode *err_value = node->data.fn_call_expr.params.at(0);
2126// TypeTableEntry *resolved_type = analyze_expression(g, import, context,
2127// g->builtin_types.entry_pure_error, err_value);
2128//
2129// if (resolved_type->id == TypeTableEntryIdInvalid) {
2130// return resolved_type;
2131// }
2132//
2133// g->generate_error_name_table = true;
2134//
2135// TypeTableEntry *str_type = get_slice_type(g, g->builtin_types.entry_u8, true);
2136// return str_type;
2137//}
2138//
2139//static TypeTableEntry *analyze_embed_file(CodeGen *g, ImportTableEntry *import,
2140// BlockContext *context, AstNode *node)
2141//{
2142// assert(node->type == NodeTypeFnCallExpr);
2143//
2144// AstNode **first_param_node = &node->data.fn_call_expr.params.at(0);
2145// Buf *rel_file_path = resolve_const_expr_str(g, import, context, first_param_node);
2146// if (!rel_file_path) {
2147// return g->builtin_types.entry_invalid;
2148// }
2149//
2150// // figure out absolute path to resource
2151// Buf source_dir_path = BUF_INIT;
2152// os_path_dirname(import->path, &source_dir_path);
2153//
2154// Buf file_path = BUF_INIT;
2155// os_path_resolve(&source_dir_path, rel_file_path, &file_path);
2156//
2157// // load from file system into const expr
2158// Buf file_contents = BUF_INIT;
2159// int err;
2160// if ((err = os_fetch_file_path(&file_path, &file_contents))) {
2161// if (err == ErrorFileNotFound) {
2162// add_node_error(g, node,
2163// buf_sprintf("unable to find '%s'", buf_ptr(&file_path)));
2164// return g->builtin_types.entry_invalid;
2165// } else {
2166// add_node_error(g, node,
2167// buf_sprintf("unable to open '%s': %s", buf_ptr(&file_path), err_str(err)));
2168// return g->builtin_types.entry_invalid;
2169// }
2170// }
2171//
2172// // TODO add dependency on the file we embedded so that we know if it changes
2173// // we'll have to invalidate the cache
2174//
2175// return resolve_expr_const_val_as_string_lit(g, node, &file_contents);
2176//}
2177//
2178//static TypeTableEntry *analyze_cmpxchg(CodeGen *g, ImportTableEntry *import,
2179// BlockContext *context, AstNode *node)
2180//{
2181// assert(node->type == NodeTypeFnCallExpr);
2182//
2183// AstNode **ptr_arg = &node->data.fn_call_expr.params.at(0);
2184// AstNode **cmp_arg = &node->data.fn_call_expr.params.at(1);
2185// AstNode **new_arg = &node->data.fn_call_expr.params.at(2);
2186// AstNode **success_order_arg = &node->data.fn_call_expr.params.at(3);
2187// AstNode **failure_order_arg = &node->data.fn_call_expr.params.at(4);
2188//
2189// TypeTableEntry *ptr_type = analyze_expression(g, import, context, nullptr, *ptr_arg);
2190// if (ptr_type->id == TypeTableEntryIdInvalid) {
2191// return g->builtin_types.entry_invalid;
2192// } else if (ptr_type->id != TypeTableEntryIdPointer) {
2193// add_node_error(g, *ptr_arg,
2194// buf_sprintf("expected pointer argument, got '%s'", buf_ptr(&ptr_type->name)));
2195// return g->builtin_types.entry_invalid;
2196// }
2197//
2198// TypeTableEntry *child_type = ptr_type->data.pointer.child_type;
2199// TypeTableEntry *cmp_type = analyze_expression(g, import, context, child_type, *cmp_arg);
2200// TypeTableEntry *new_type = analyze_expression(g, import, context, child_type, *new_arg);
2201//
2202// TypeTableEntry *success_order_type = analyze_expression(g, import, context,
2203// g->builtin_types.entry_atomic_order_enum, *success_order_arg);
2204// TypeTableEntry *failure_order_type = analyze_expression(g, import, context,
2205// g->builtin_types.entry_atomic_order_enum, *failure_order_arg);
2206//
2207// if (cmp_type->id == TypeTableEntryIdInvalid ||
2208// new_type->id == TypeTableEntryIdInvalid ||
2209// success_order_type->id == TypeTableEntryIdInvalid ||
2210// failure_order_type->id == TypeTableEntryIdInvalid)
2211// {
2212// return g->builtin_types.entry_invalid;
2213// }
2214//
2215// ConstExprValue *success_order_val = &get_resolved_expr(*success_order_arg)->const_val;
2216// ConstExprValue *failure_order_val = &get_resolved_expr(*failure_order_arg)->const_val;
2217// if (!success_order_val->ok) {
2218// add_node_error(g, *success_order_arg, buf_sprintf("unable to evaluate constant expression"));
2219// return g->builtin_types.entry_invalid;
2220// } else if (!failure_order_val->ok) {
2221// add_node_error(g, *failure_order_arg, buf_sprintf("unable to evaluate constant expression"));
2222// return g->builtin_types.entry_invalid;
2223// }
2224//
2225// if (success_order_val->data.x_enum.tag < AtomicOrderMonotonic) {
2226// add_node_error(g, *success_order_arg,
2227// buf_sprintf("success atomic ordering must be Monotonic or stricter"));
2228// return g->builtin_types.entry_invalid;
2229// }
2230// if (failure_order_val->data.x_enum.tag < AtomicOrderMonotonic) {
2231// add_node_error(g, *failure_order_arg,
2232// buf_sprintf("failure atomic ordering must be Monotonic or stricter"));
2233// return g->builtin_types.entry_invalid;
2234// }
2235// if (failure_order_val->data.x_enum.tag > success_order_val->data.x_enum.tag) {
2236// add_node_error(g, *failure_order_arg,
2237// buf_sprintf("failure atomic ordering must be no stricter than success"));
2238// return g->builtin_types.entry_invalid;
2239// }
2240// if (failure_order_val->data.x_enum.tag == AtomicOrderRelease ||
2241// failure_order_val->data.x_enum.tag == AtomicOrderAcqRel)
2242// {
2243// add_node_error(g, *failure_order_arg,
2244// buf_sprintf("failure atomic ordering must not be Release or AcqRel"));
2245// return g->builtin_types.entry_invalid;
2246// }
2247//
2248// return g->builtin_types.entry_bool;
2249//}
2250//
2251//static TypeTableEntry *analyze_fence(CodeGen *g, ImportTableEntry *import,
2252// BlockContext *context, AstNode *node)
2253//{
2254// assert(node->type == NodeTypeFnCallExpr);
2255//
2256// AstNode **atomic_order_arg = &node->data.fn_call_expr.params.at(0);
2257// TypeTableEntry *atomic_order_type = analyze_expression(g, import, context,
2258// g->builtin_types.entry_atomic_order_enum, *atomic_order_arg);
2259//
2260// if (atomic_order_type->id == TypeTableEntryIdInvalid) {
2261// return g->builtin_types.entry_invalid;
2262// }
2263//
2264// ConstExprValue *atomic_order_val = &get_resolved_expr(*atomic_order_arg)->const_val;
2265//
2266// if (!atomic_order_val->ok) {
2267// add_node_error(g, *atomic_order_arg, buf_sprintf("unable to evaluate constant expression"));
2268// return g->builtin_types.entry_invalid;
2269// }
2270//
2271// return g->builtin_types.entry_void;
2272//}
2273//
2274//static TypeTableEntry *analyze_div_exact(CodeGen *g, ImportTableEntry *import,
2275// BlockContext *context, AstNode *node)
2276//{
2277// assert(node->type == NodeTypeFnCallExpr);
2278//
2279// AstNode **op1 = &node->data.fn_call_expr.params.at(0);
2280// AstNode **op2 = &node->data.fn_call_expr.params.at(1);
2281//
2282// TypeTableEntry *op1_type = analyze_expression(g, import, context, nullptr, *op1);
2283// TypeTableEntry *op2_type = analyze_expression(g, import, context, nullptr, *op2);
2284//
2285// AstNode *op_nodes[] = {*op1, *op2};
2286// TypeTableEntry *op_types[] = {op1_type, op2_type};
2287// TypeTableEntry *result_type = resolve_peer_type_compatibility(g, import, context, node,
2288// op_nodes, op_types, 2);
2289//
2290// if (result_type->id == TypeTableEntryIdInvalid) {
2291// return g->builtin_types.entry_invalid;
2292// } else if (result_type->id == TypeTableEntryIdInt) {
2293// return result_type;
2294// } else if (result_type->id == TypeTableEntryIdNumLitInt) {
2295// // check for division by zero
2296// // check for non exact division
2297// zig_panic("TODO");
2298// } else {
2299// add_node_error(g, node,
2300// buf_sprintf("expected integer type, got '%s'", buf_ptr(&result_type->name)));
2301// return g->builtin_types.entry_invalid;
2302// }
2303//}
2304//
2305//static TypeTableEntry *analyze_truncate(CodeGen *g, ImportTableEntry *import,
2306// BlockContext *context, AstNode *node)
2307//{
2308// assert(node->type == NodeTypeFnCallExpr);
2309//
2310// AstNode **op1 = &node->data.fn_call_expr.params.at(0);
2311// AstNode **op2 = &node->data.fn_call_expr.params.at(1);
2312//
2313// TypeTableEntry *dest_type = analyze_type_expr(g, import, context, *op1);
2314// TypeTableEntry *src_type = analyze_expression(g, import, context, nullptr, *op2);
2315//
2316// if (dest_type->id == TypeTableEntryIdInvalid || src_type->id == TypeTableEntryIdInvalid) {
2317// return g->builtin_types.entry_invalid;
2318// } else if (dest_type->id != TypeTableEntryIdInt) {
2319// add_node_error(g, *op1,
2320// buf_sprintf("expected integer type, got '%s'", buf_ptr(&dest_type->name)));
2321// return g->builtin_types.entry_invalid;
2322// } else if (src_type->id != TypeTableEntryIdInt) {
2323// add_node_error(g, *op2,
2324// buf_sprintf("expected integer type, got '%s'", buf_ptr(&src_type->name)));
2325// return g->builtin_types.entry_invalid;
2326// } else if (src_type->data.integral.is_signed != dest_type->data.integral.is_signed) {
2327// const char *sign_str = dest_type->data.integral.is_signed ? "signed" : "unsigned";
2328// add_node_error(g, *op2,
2329// buf_sprintf("expected %s integer type, got '%s'", sign_str, buf_ptr(&src_type->name)));
2330// return g->builtin_types.entry_invalid;
2331// } else if (src_type->data.integral.bit_count <= dest_type->data.integral.bit_count) {
2332// add_node_error(g, *op2,
2333// buf_sprintf("type '%s' has same or fewer bits than destination type '%s'",
2334// buf_ptr(&src_type->name), buf_ptr(&dest_type->name)));
2335// return g->builtin_types.entry_invalid;
2336// }
2337//
2338// // TODO const expr eval
2339//
2340// return dest_type;
2341//}
2342//
2343//static TypeTableEntry *analyze_compile_err(CodeGen *g, ImportTableEntry *import,
2344// BlockContext *context, AstNode *node)
2345//{
2346// AstNode *first_param_node = node->data.fn_call_expr.params.at(0);
2347// Buf *err_msg = resolve_const_expr_str(g, import, context, first_param_node->parent_field);
2348// if (!err_msg) {
2349// return g->builtin_types.entry_invalid;
2350// }
2351//
2352// add_node_error(g, node, err_msg);
2353//
2354// return g->builtin_types.entry_invalid;
2355//}
2356//
2357//static TypeTableEntry *analyze_int_type(CodeGen *g, ImportTableEntry *import,
2358// BlockContext *context, AstNode *node)
2359//{
2360// AstNode **is_signed_node = &node->data.fn_call_expr.params.at(0);
2361// AstNode **bit_count_node = &node->data.fn_call_expr.params.at(1);
2362//
2363// TypeTableEntry *bool_type = g->builtin_types.entry_bool;
2364// TypeTableEntry *usize_type = g->builtin_types.entry_usize;
2365// TypeTableEntry *is_signed_type = analyze_expression(g, import, context, bool_type, *is_signed_node);
2366// TypeTableEntry *bit_count_type = analyze_expression(g, import, context, usize_type, *bit_count_node);
2367//
2368// if (is_signed_type->id == TypeTableEntryIdInvalid ||
2369// bit_count_type->id == TypeTableEntryIdInvalid)
2370// {
2371// return g->builtin_types.entry_invalid;
2372// }
2373//
2374// ConstExprValue *is_signed_val = &get_resolved_expr(*is_signed_node)->const_val;
2375// ConstExprValue *bit_count_val = &get_resolved_expr(*bit_count_node)->const_val;
2376//
2377// AstNode *bad_node = nullptr;
2378// if (!is_signed_val->ok) {
2379// bad_node = *is_signed_node;
2380// } else if (!bit_count_val->ok) {
2381// bad_node = *bit_count_node;
2382// }
2383// if (bad_node) {
2384// add_node_error(g, bad_node, buf_sprintf("unable to evaluate constant expression"));
2385// return g->builtin_types.entry_invalid;
2386// }
2387//
2388// bool depends_on_compile_var = is_signed_val->depends_on_compile_var || bit_count_val->depends_on_compile_var;
2389//
2390// TypeTableEntry *int_type = get_int_type(g, is_signed_val->data.x_bool,
2391// bit_count_val->data.x_bignum.data.x_uint);
2392// return resolve_expr_const_val_as_type(g, node, int_type, depends_on_compile_var);
2393//
2394//}
2395//
2396//static TypeTableEntry *analyze_set_fn_test(CodeGen *g, ImportTableEntry *import,
2397// BlockContext *context, AstNode *node)
2398//{
2399// AstNode **fn_node = &node->data.fn_call_expr.params.at(0);
2400// AstNode **value_node = &node->data.fn_call_expr.params.at(1);
2401//
2402// FnTableEntry *fn_entry = resolve_const_expr_fn(g, import, context, fn_node);
2403// if (!fn_entry) {
2404// return g->builtin_types.entry_invalid;
2405// }
2406//
2407// bool ok = resolve_const_expr_bool(g, import, context, value_node, &fn_entry->is_test);
2408// if (!ok) {
2409// return g->builtin_types.entry_invalid;
2410// }
2411//
2412// if (fn_entry->fn_test_set_node) {
2413// ErrorMsg *msg = add_node_error(g, node, buf_sprintf("function test attribute set twice"));
2414// add_error_note(g, msg, fn_entry->fn_test_set_node, buf_sprintf("first set here"));
2415// return g->builtin_types.entry_invalid;
2416// }
2417// fn_entry->fn_test_set_node = node;
2418//
2419// g->test_fn_count += 1;
2420// return g->builtin_types.entry_void;
2421//}
2422//
2423//static TypeTableEntry *analyze_set_fn_no_inline(CodeGen *g, ImportTableEntry *import,
2424// BlockContext *context, AstNode *node)
2425//{
2426// AstNode **fn_node = &node->data.fn_call_expr.params.at(0);
2427// AstNode **value_node = &node->data.fn_call_expr.params.at(1);
2428//
2429// FnTableEntry *fn_entry = resolve_const_expr_fn(g, import, context, fn_node);
2430// if (!fn_entry) {
2431// return g->builtin_types.entry_invalid;
2432// }
2433//
2434// bool is_noinline;
2435// bool ok = resolve_const_expr_bool(g, import, context, value_node, &is_noinline);
2436// if (!ok) {
2437// return g->builtin_types.entry_invalid;
2438// }
2439//
2440// if (fn_entry->fn_no_inline_set_node) {
2441// ErrorMsg *msg = add_node_error(g, node, buf_sprintf("function no inline attribute set twice"));
2442// add_error_note(g, msg, fn_entry->fn_no_inline_set_node, buf_sprintf("first set here"));
2443// return g->builtin_types.entry_invalid;
2444// }
2445// fn_entry->fn_no_inline_set_node = node;
2446//
2447// if (fn_entry->fn_inline == FnInlineAlways) {
2448// add_node_error(g, node, buf_sprintf("function is both inline and noinline"));
2449// fn_entry->proto_node->data.fn_proto.skip = true;
2450// return g->builtin_types.entry_invalid;
2451// } else if (is_noinline) {
2452// fn_entry->fn_inline = FnInlineNever;
2453// }
2454//
2455// return g->builtin_types.entry_void;
2456//}
2457//
2458//static TypeTableEntry *analyze_set_fn_static_eval(CodeGen *g, ImportTableEntry *import,
2459// BlockContext *context, AstNode *node)
2460//{
2461// AstNode **fn_node = &node->data.fn_call_expr.params.at(0);
2462// AstNode **value_node = &node->data.fn_call_expr.params.at(1);
2463//
2464// FnTableEntry *fn_entry = resolve_const_expr_fn(g, import, context, fn_node);
2465// if (!fn_entry) {
2466// return g->builtin_types.entry_invalid;
2467// }
2468//
2469// bool want_static_eval;
2470// bool ok = resolve_const_expr_bool(g, import, context, value_node, &want_static_eval);
2471// if (!ok) {
2472// return g->builtin_types.entry_invalid;
2473// }
2474//
2475// if (fn_entry->fn_static_eval_set_node) {
2476// ErrorMsg *msg = add_node_error(g, node, buf_sprintf("function static eval attribute set twice"));
2477// add_error_note(g, msg, fn_entry->fn_static_eval_set_node, buf_sprintf("first set here"));
2478// return g->builtin_types.entry_invalid;
2479// }
2480// fn_entry->fn_static_eval_set_node = node;
2481//
2482// if (want_static_eval && !context->fn_entry->is_pure) {
2483// add_node_error(g, node, buf_sprintf("attribute appears too late within function"));
2484// return g->builtin_types.entry_invalid;
2485// }
2486//
2487// if (want_static_eval) {
2488// fn_entry->want_pure = WantPureTrue;
2489// fn_entry->want_pure_attr_node = node;
2490// } else {
2491// fn_entry->want_pure = WantPureFalse;
2492// fn_entry->is_pure = false;
2493// }
2494//
2495// return g->builtin_types.entry_void;
2496//}
2497//
2498//static TypeTableEntry *analyze_set_fn_visible(CodeGen *g, ImportTableEntry *import,
2499// BlockContext *context, AstNode *node)
2500//{
2501// AstNode **fn_node = &node->data.fn_call_expr.params.at(0);
2502// AstNode **value_node = &node->data.fn_call_expr.params.at(1);
2503//
2504// FnTableEntry *fn_entry = resolve_const_expr_fn(g, import, context, fn_node);
2505// if (!fn_entry) {
2506// return g->builtin_types.entry_invalid;
2507// }
2508//
2509// bool want_export;
2510// bool ok = resolve_const_expr_bool(g, import, context, value_node, &want_export);
2511// if (!ok) {
2512// return g->builtin_types.entry_invalid;
2513// }
2514//
2515// if (fn_entry->fn_export_set_node) {
2516// ErrorMsg *msg = add_node_error(g, node, buf_sprintf("function visibility set twice"));
2517// add_error_note(g, msg, fn_entry->fn_export_set_node, buf_sprintf("first set here"));
2518// return g->builtin_types.entry_invalid;
2519// }
2520// fn_entry->fn_export_set_node = node;
2521//
2522// AstNodeFnProto *fn_proto = &fn_entry->proto_node->data.fn_proto;
2523// if (fn_proto->top_level_decl.visib_mod != VisibModExport) {
2524// ErrorMsg *msg = add_node_error(g, node,
2525// buf_sprintf("function must be marked export to set function visibility"));
2526// add_error_note(g, msg, fn_entry->proto_node, buf_sprintf("function declared here"));
2527// return g->builtin_types.entry_void;
2528// }
2529// if (!want_export) {
2530// fn_proto->top_level_decl.visib_mod = VisibModPub;
2531// }
2532//
2533// return g->builtin_types.entry_void;
2534//}
2535//
2536//static TypeTableEntry *analyze_set_debug_safety(CodeGen *g, ImportTableEntry *import,
2537// BlockContext *parent_context, AstNode *node)
2538//{
2539// AstNode **target_node = &node->data.fn_call_expr.params.at(0);
2540// AstNode **value_node = &node->data.fn_call_expr.params.at(1);
2541//
2542// TypeTableEntry *target_type = analyze_expression(g, import, parent_context, nullptr, *target_node);
2543// BlockContext *target_context;
2544// ConstExprValue *const_val = &get_resolved_expr(*target_node)->const_val;
2545// if (target_type->id == TypeTableEntryIdInvalid) {
2546// return g->builtin_types.entry_invalid;
2547// }
2548// if (!const_val->ok) {
2549// add_node_error(g, *target_node, buf_sprintf("unable to evaluate constant expression"));
2550// return g->builtin_types.entry_invalid;
2551// }
2552// if (target_type->id == TypeTableEntryIdBlock) {
2553// target_context = const_val->data.x_block;
2554// } else if (target_type->id == TypeTableEntryIdFn) {
2555// target_context = const_val->data.x_fn->fn_def_node->data.fn_def.block_context;
2556// } else if (target_type->id == TypeTableEntryIdMetaType) {
2557// TypeTableEntry *type_arg = const_val->data.x_type;
2558// if (type_arg->id == TypeTableEntryIdStruct) {
2559// target_context = type_arg->data.structure.block_context;
2560// } else if (type_arg->id == TypeTableEntryIdEnum) {
2561// target_context = type_arg->data.enumeration.block_context;
2562// } else if (type_arg->id == TypeTableEntryIdUnion) {
2563// target_context = type_arg->data.unionation.block_context;
2564// } else {
2565// add_node_error(g, *target_node,
2566// buf_sprintf("expected scope reference, got type '%s'", buf_ptr(&type_arg->name)));
2567// return g->builtin_types.entry_invalid;
2568// }
2569// } else {
2570// add_node_error(g, *target_node,
2571// buf_sprintf("expected scope reference, got type '%s'", buf_ptr(&target_type->name)));
2572// return g->builtin_types.entry_invalid;
2573// }
2574//
2575// bool want_debug_safety;
2576// bool ok = resolve_const_expr_bool(g, import, parent_context, value_node, &want_debug_safety);
2577// if (!ok) {
2578// return g->builtin_types.entry_invalid;
2579// }
2580//
2581// if (target_context->safety_set_node) {
2582// ErrorMsg *msg = add_node_error(g, node, buf_sprintf("debug safety for scope set twice"));
2583// add_error_note(g, msg, target_context->safety_set_node, buf_sprintf("first set here"));
2584// return g->builtin_types.entry_invalid;
2585// }
2586// target_context->safety_set_node = node;
2587//
2588// target_context->safety_off = !want_debug_safety;
2589//
2590// return g->builtin_types.entry_void;
2591//}
2592
2593
2594//static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
2595// TypeTableEntry *expected_type, AstNode *node)
2596//{
2597//
2598// switch (builtin_fn->id) {
2599// case BuiltinFnIdInvalid:
2600// zig_unreachable();
2601// case BuiltinFnIdAddWithOverflow:
2602// case BuiltinFnIdSubWithOverflow:
2603// case BuiltinFnIdMulWithOverflow:
2604// case BuiltinFnIdShlWithOverflow:
2605// {
2606// AstNode *type_node = node->data.fn_call_expr.params.at(0);
2607// TypeTableEntry *int_type = analyze_type_expr(g, import, context, type_node);
2608// if (int_type->id == TypeTableEntryIdInvalid) {
2609// return g->builtin_types.entry_bool;
2610// } else if (int_type->id == TypeTableEntryIdInt) {
2611// AstNode *op1_node = node->data.fn_call_expr.params.at(1);
2612// AstNode *op2_node = node->data.fn_call_expr.params.at(2);
2613// AstNode *result_node = node->data.fn_call_expr.params.at(3);
2614//
2615// analyze_expression(g, import, context, int_type, op1_node);
2616// analyze_expression(g, import, context, int_type, op2_node);
2617// analyze_expression(g, import, context, get_pointer_to_type(g, int_type, false),
2618// result_node);
2619// } else {
2620// add_node_error(g, type_node,
2621// buf_sprintf("expected integer type, got '%s'", buf_ptr(&int_type->name)));
2622// }
2623//
2624// // TODO constant expression evaluation
2625//
2626// return g->builtin_types.entry_bool;
2627// }
2628// case BuiltinFnIdMemcpy:
2629// {
2630// AstNode *dest_node = node->data.fn_call_expr.params.at(0);
2631// AstNode *src_node = node->data.fn_call_expr.params.at(1);
2632// AstNode *len_node = node->data.fn_call_expr.params.at(2);
2633// TypeTableEntry *dest_type = analyze_expression(g, import, context, nullptr, dest_node);
2634// TypeTableEntry *src_type = analyze_expression(g, import, context, nullptr, src_node);
2635// analyze_expression(g, import, context, builtin_fn->param_types[2], len_node);
2636//
2637// if (dest_type->id != TypeTableEntryIdInvalid &&
2638// dest_type->id != TypeTableEntryIdPointer)
2639// {
2640// add_node_error(g, dest_node,
2641// buf_sprintf("expected pointer argument, got '%s'", buf_ptr(&dest_type->name)));
2642// }
2643//
2644// if (src_type->id != TypeTableEntryIdInvalid &&
2645// src_type->id != TypeTableEntryIdPointer)
2646// {
2647// add_node_error(g, src_node,
2648// buf_sprintf("expected pointer argument, got '%s'", buf_ptr(&src_type->name)));
2649// }
2650//
2651// if (dest_type->id == TypeTableEntryIdPointer &&
2652// src_type->id == TypeTableEntryIdPointer)
2653// {
2654// uint64_t dest_align = get_memcpy_align(g, dest_type->data.pointer.child_type);
2655// uint64_t src_align = get_memcpy_align(g, src_type->data.pointer.child_type);
2656// if (dest_align != src_align) {
2657// add_node_error(g, dest_node, buf_sprintf(
2658// "misaligned memcpy, '%s' has alignment '%" PRIu64 ", '%s' has alignment %" PRIu64,
2659// buf_ptr(&dest_type->name), dest_align,
2660// buf_ptr(&src_type->name), src_align));
2661// }
2662// }
2663//
2664// return builtin_fn->return_type;
2665// }
2666// case BuiltinFnIdMemset:
2667// {
2668// AstNode *dest_node = node->data.fn_call_expr.params.at(0);
2669// AstNode *char_node = node->data.fn_call_expr.params.at(1);
2670// AstNode *len_node = node->data.fn_call_expr.params.at(2);
2671// TypeTableEntry *dest_type = analyze_expression(g, import, context, nullptr, dest_node);
2672// analyze_expression(g, import, context, builtin_fn->param_types[1], char_node);
2673// analyze_expression(g, import, context, builtin_fn->param_types[2], len_node);
2674//
2675// if (dest_type->id != TypeTableEntryIdInvalid &&
2676// dest_type->id != TypeTableEntryIdPointer)
2677// {
2678// add_node_error(g, dest_node,
2679// buf_sprintf("expected pointer argument, got '%s'", buf_ptr(&dest_type->name)));
2680// }
2681//
2682// return builtin_fn->return_type;
2683// }
2684// case BuiltinFnIdSizeof:
2685// {
2686// AstNode *type_node = node->data.fn_call_expr.params.at(0);
2687// TypeTableEntry *type_entry = analyze_type_expr(g, import, context, type_node);
2688// if (type_entry->id == TypeTableEntryIdInvalid) {
2689// return g->builtin_types.entry_invalid;
2690// } else if (type_entry->id == TypeTableEntryIdUnreachable) {
2691// add_node_error(g, first_executing_node(type_node),
2692// buf_sprintf("no size available for type '%s'", buf_ptr(&type_entry->name)));
2693// return g->builtin_types.entry_invalid;
2694// } else {
2695// uint64_t size_in_bytes = type_size(g, type_entry);
2696// bool depends_on_compile_var = (type_entry == g->builtin_types.entry_usize ||
2697// type_entry == g->builtin_types.entry_isize);
2698// return resolve_expr_const_val_as_unsigned_num_lit(g, node, expected_type,
2699// size_in_bytes, depends_on_compile_var);
2700// }
2701// }
2702// case BuiltinFnIdAlignof:
2703// {
2704// AstNode *type_node = node->data.fn_call_expr.params.at(0);
2705// TypeTableEntry *type_entry = analyze_type_expr(g, import, context, type_node);
2706// if (type_entry->id == TypeTableEntryIdInvalid) {
2707// return g->builtin_types.entry_invalid;
2708// } else if (type_entry->id == TypeTableEntryIdUnreachable) {
2709// add_node_error(g, first_executing_node(type_node),
2710// buf_sprintf("no align available for type '%s'", buf_ptr(&type_entry->name)));
2711// return g->builtin_types.entry_invalid;
2712// } else {
2713// uint64_t align_in_bytes = LLVMABISizeOfType(g->target_data_ref, type_entry->type_ref);
2714// return resolve_expr_const_val_as_unsigned_num_lit(g, node, expected_type,
2715// align_in_bytes, false);
2716// }
2717// }
2718// case BuiltinFnIdMaxValue:
2719// return analyze_min_max_value(g, import, context, node,
2720// "no max value available for type '%s'", true);
2721// case BuiltinFnIdMinValue:
2722// return analyze_min_max_value(g, import, context, node,
2723// "no min value available for type '%s'", false);
2724// case BuiltinFnIdMemberCount:
2725// {
2726// AstNode *type_node = node->data.fn_call_expr.params.at(0);
2727// TypeTableEntry *type_entry = analyze_type_expr(g, import, context, type_node);
2728//
2729// if (type_entry->id == TypeTableEntryIdInvalid) {
2730// return type_entry;
2731// } else if (type_entry->id == TypeTableEntryIdEnum) {
2732// uint64_t value_count = type_entry->data.enumeration.src_field_count;
2733// return resolve_expr_const_val_as_unsigned_num_lit(g, node, expected_type,
2734// value_count, false);
2735// } else {
2736// add_node_error(g, node,
2737// buf_sprintf("no value count available for type '%s'", buf_ptr(&type_entry->name)));
2738// return g->builtin_types.entry_invalid;
2739// }
2740// }
2741// case BuiltinFnIdTypeof:
2742// {
2743// AstNode *expr_node = node->data.fn_call_expr.params.at(0);
2744// TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, expr_node);
2745//
2746// switch (type_entry->id) {
2747// case TypeTableEntryIdInvalid:
2748// return type_entry;
2749// case TypeTableEntryIdNumLitFloat:
2750// case TypeTableEntryIdNumLitInt:
2751// case TypeTableEntryIdUndefLit:
2752// case TypeTableEntryIdNullLit:
2753// case TypeTableEntryIdNamespace:
2754// case TypeTableEntryIdBlock:
2755// case TypeTableEntryIdGenericFn:
2756// case TypeTableEntryIdVar:
2757// add_node_error(g, expr_node,
2758// buf_sprintf("type '%s' not eligible for @typeOf", buf_ptr(&type_entry->name)));
2759// return g->builtin_types.entry_invalid;
2760// case TypeTableEntryIdMetaType:
2761// case TypeTableEntryIdVoid:
2762// case TypeTableEntryIdBool:
2763// case TypeTableEntryIdUnreachable:
2764// case TypeTableEntryIdInt:
2765// case TypeTableEntryIdFloat:
2766// case TypeTableEntryIdPointer:
2767// case TypeTableEntryIdArray:
2768// case TypeTableEntryIdStruct:
2769// case TypeTableEntryIdMaybe:
2770// case TypeTableEntryIdErrorUnion:
2771// case TypeTableEntryIdPureError:
2772// case TypeTableEntryIdEnum:
2773// case TypeTableEntryIdUnion:
2774// case TypeTableEntryIdFn:
2775// case TypeTableEntryIdTypeDecl:
2776// return resolve_expr_const_val_as_type(g, node, type_entry, false);
2777// }
2778// }
2779// case BuiltinFnIdCInclude:
2780// {
2781// if (!context->c_import_buf) {
2782// add_node_error(g, node, buf_sprintf("@c_include valid only in c_import blocks"));
2783// return g->builtin_types.entry_invalid;
2784// }
2785//
2786// AstNode **str_node = node->data.fn_call_expr.params.at(0)->parent_field;
2787// TypeTableEntry *str_type = get_slice_type(g, g->builtin_types.entry_u8, true);
2788// TypeTableEntry *resolved_type = analyze_expression(g, import, context, str_type, *str_node);
2789//
2790// if (resolved_type->id == TypeTableEntryIdInvalid) {
2791// return resolved_type;
2792// }
2793//
2794// ConstExprValue *const_str_val = &get_resolved_expr(*str_node)->const_val;
2795//
2796// if (!const_str_val->ok) {
2797// add_node_error(g, *str_node, buf_sprintf("@c_include requires constant expression"));
2798// return g->builtin_types.entry_void;
2799// }
2800//
2801// buf_appendf(context->c_import_buf, "#include <");
2802// ConstExprValue *ptr_field = const_str_val->data.x_struct.fields[0];
2803// uint64_t len = ptr_field->data.x_ptr.len;
2804// for (uint64_t i = 0; i < len; i += 1) {
2805// ConstExprValue *char_val = ptr_field->data.x_ptr.ptr[i];
2806// uint64_t big_c = char_val->data.x_bignum.data.x_uint;
2807// assert(big_c <= UINT8_MAX);
2808// uint8_t c = big_c;
2809// buf_append_char(context->c_import_buf, c);
2810// }
2811// buf_appendf(context->c_import_buf, ">\n");
2812//
2813// return g->builtin_types.entry_void;
2814// }
2815// case BuiltinFnIdCDefine:
2816// zig_panic("TODO");
2817// case BuiltinFnIdCUndef:
2818// zig_panic("TODO");
2819//
2820// case BuiltinFnIdCompileVar:
2821// {
2822// AstNode **str_node = node->data.fn_call_expr.params.at(0)->parent_field;
2823//
2824// Buf *var_name = resolve_const_expr_str(g, import, context, str_node);
2825// if (!var_name) {
2826// return g->builtin_types.entry_invalid;
2827// }
2828//
2829// ConstExprValue *const_val = &get_resolved_expr(node)->const_val;
2830// const_val->ok = true;
2831// const_val->depends_on_compile_var = true;
2832//
2833// if (buf_eql_str(var_name, "is_big_endian")) {
2834// return resolve_expr_const_val_as_bool(g, node, g->is_big_endian, true);
2835// } else if (buf_eql_str(var_name, "is_release")) {
2836// return resolve_expr_const_val_as_bool(g, node, g->is_release_build, true);
2837// } else if (buf_eql_str(var_name, "is_test")) {
2838// return resolve_expr_const_val_as_bool(g, node, g->is_test_build, true);
2839// } else if (buf_eql_str(var_name, "os")) {
2840// const_val->data.x_enum.tag = g->target_os_index;
2841// return g->builtin_types.entry_os_enum;
2842// } else if (buf_eql_str(var_name, "arch")) {
2843// const_val->data.x_enum.tag = g->target_arch_index;
2844// return g->builtin_types.entry_arch_enum;
2845// } else if (buf_eql_str(var_name, "environ")) {
2846// const_val->data.x_enum.tag = g->target_environ_index;
2847// return g->builtin_types.entry_environ_enum;
2848// } else if (buf_eql_str(var_name, "object_format")) {
2849// const_val->data.x_enum.tag = g->target_oformat_index;
2850// return g->builtin_types.entry_oformat_enum;
2851// } else {
2852// add_node_error(g, *str_node,
2853// buf_sprintf("unrecognized compile variable: '%s'", buf_ptr(var_name)));
2854// return g->builtin_types.entry_invalid;
2855// }
2856// }
2857// case BuiltinFnIdConstEval:
2858// {
2859// AstNode **expr_node = node->data.fn_call_expr.params.at(0)->parent_field;
2860// TypeTableEntry *resolved_type = analyze_expression(g, import, context, expected_type, *expr_node);
2861// if (resolved_type->id == TypeTableEntryIdInvalid) {
2862// return resolved_type;
2863// }
2864//
2865// ConstExprValue *const_expr_val = &get_resolved_expr(*expr_node)->const_val;
2866//
2867// if (!const_expr_val->ok) {
2868// add_node_error(g, *expr_node, buf_sprintf("unable to evaluate constant expression"));
2869// return g->builtin_types.entry_invalid;
2870// }
2871//
2872// ConstExprValue *const_val = &get_resolved_expr(node)->const_val;
2873// *const_val = *const_expr_val;
2874//
2875// return resolved_type;
2876// }
2877// case BuiltinFnIdCtz:
2878// case BuiltinFnIdClz:
2879// {
2880// AstNode *type_node = node->data.fn_call_expr.params.at(0);
2881// TypeTableEntry *int_type = analyze_type_expr(g, import, context, type_node);
2882// if (int_type->id == TypeTableEntryIdInvalid) {
2883// return int_type;
2884// } else if (int_type->id == TypeTableEntryIdInt) {
2885// AstNode **expr_node = node->data.fn_call_expr.params.at(1)->parent_field;
2886// TypeTableEntry *resolved_type = analyze_expression(g, import, context, int_type, *expr_node);
2887// if (resolved_type->id == TypeTableEntryIdInvalid) {
2888// return resolved_type;
2889// }
2890//
2891// // TODO const expr eval
2892//
2893// return resolved_type;
2894// } else {
2895// add_node_error(g, type_node,
2896// buf_sprintf("expected integer type, got '%s'", buf_ptr(&int_type->name)));
2897// return g->builtin_types.entry_invalid;
2898// }
2899// }
2900// case BuiltinFnIdImport:
2901// return analyze_import(g, import, context, node);
2902// case BuiltinFnIdCImport:
2903// return analyze_c_import(g, import, context, node);
2904// case BuiltinFnIdErrName:
2905// return analyze_err_name(g, import, context, node);
2906// case BuiltinFnIdBreakpoint:
2907// mark_impure_fn(g, context, node);
2908// return g->builtin_types.entry_void;
2909// case BuiltinFnIdReturnAddress:
2910// case BuiltinFnIdFrameAddress:
2911// mark_impure_fn(g, context, node);
2912// return builtin_fn->return_type;
2913// case BuiltinFnIdEmbedFile:
2914// return analyze_embed_file(g, import, context, node);
2915// case BuiltinFnIdCmpExchange:
2916// return analyze_cmpxchg(g, import, context, node);
2917// case BuiltinFnIdFence:
2918// return analyze_fence(g, import, context, node);
2919// case BuiltinFnIdDivExact:
2920// return analyze_div_exact(g, import, context, node);
2921// case BuiltinFnIdTruncate:
2922// return analyze_truncate(g, import, context, node);
2923// case BuiltinFnIdCompileErr:
2924// return analyze_compile_err(g, import, context, node);
2925// case BuiltinFnIdIntType:
2926// return analyze_int_type(g, import, context, node);
2927// case BuiltinFnIdUnreachable:
2928// return g->builtin_types.entry_unreachable;
2929// case BuiltinFnIdSetFnTest:
2930// return analyze_set_fn_test(g, import, context, node);
2931// case BuiltinFnIdSetFnNoInline:
2932// return analyze_set_fn_no_inline(g, import, context, node);
2933// case BuiltinFnIdSetFnStaticEval:
2934// return analyze_set_fn_static_eval(g, import, context, node);
2935// case BuiltinFnIdSetFnVisible:
2936// return analyze_set_fn_visible(g, import, context, node);
2937// case BuiltinFnIdSetDebugSafety:
2938// return analyze_set_debug_safety(g, import, context, node);
2939// }
2940// zig_unreachable();
2941//}
2942
2943
1528static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {2944static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {
1529 switch (instruction->id) {2945 switch (instruction->id) {
1530 case IrInstructionIdInvalid:2946 case IrInstructionIdInvalid:
...@@ -1533,6 +2949,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi...@@ -1533,6 +2949,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
1533 return ir_analyze_instruction_return(ira, (IrInstructionReturn *)instruction);2949 return ir_analyze_instruction_return(ira, (IrInstructionReturn *)instruction);
1534 case IrInstructionIdConst:2950 case IrInstructionIdConst:
1535 return ir_analyze_instruction_const(ira, (IrInstructionConst *)instruction);2951 return ir_analyze_instruction_const(ira, (IrInstructionConst *)instruction);
2952 case IrInstructionIdUnOp:
2953 return ir_analyze_instruction_un_op(ira, (IrInstructionUnOp *)instruction);
1536 case IrInstructionIdBinOp:2954 case IrInstructionIdBinOp:
1537 return ir_analyze_instruction_bin_op(ira, (IrInstructionBinOp *)instruction);2955 return ir_analyze_instruction_bin_op(ira, (IrInstructionBinOp *)instruction);
1538 case IrInstructionIdLoadVar:2956 case IrInstructionIdLoadVar:
...@@ -1540,6 +2958,7 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi...@@ -1540,6 +2958,7 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
1540 case IrInstructionIdCall:2958 case IrInstructionIdCall:
1541 return ir_analyze_instruction_call(ira, (IrInstructionCall *)instruction);2959 return ir_analyze_instruction_call(ira, (IrInstructionCall *)instruction);
1542 case IrInstructionIdCondBr:2960 case IrInstructionIdCondBr:
2961 case IrInstructionIdBr:
1543 case IrInstructionIdSwitchBr:2962 case IrInstructionIdSwitchBr:
1544 case IrInstructionIdPhi:2963 case IrInstructionIdPhi:
1545 case IrInstructionIdStoreVar:2964 case IrInstructionIdStoreVar:
...@@ -1582,9 +3001,7 @@ TypeTableEntry *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutabl...@@ -1582,9 +3001,7 @@ TypeTableEntry *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutabl
15823001
1583 TypeTableEntry *return_type = ira->codegen->builtin_types.entry_void;3002 TypeTableEntry *return_type = ira->codegen->builtin_types.entry_void;
15843003
1585 ira->new_irb.current_basic_block = allocate<IrBasicBlock>(1);3004 ira->new_irb.current_basic_block = ir_build_basic_block(&ira->new_irb, "Entry");
1586 ira->new_irb.exec->basic_block_list.append(ira->new_irb.current_basic_block);
1587
1588 ira->old_irb.current_basic_block = ira->old_irb.exec->basic_block_list.at(0);3005 ira->old_irb.current_basic_block = ira->old_irb.exec->basic_block_list.at(0);
15893006
1590 ira->new_irb.current_basic_block->other = ira->old_irb.current_basic_block;3007 ira->new_irb.current_basic_block->other = ira->old_irb.current_basic_block;
src/ir_print.cpp+105-3
...@@ -46,10 +46,17 @@ static void ir_print_const(IrPrint *irp, IrInstructionConst *const_instruction)...@@ -46,10 +46,17 @@ static void ir_print_const(IrPrint *irp, IrInstructionConst *const_instruction)
46 case TypeTableEntryIdMetaType:46 case TypeTableEntryIdMetaType:
47 fprintf(irp->f, "%s\n", buf_ptr(&const_instruction->base.static_value.data.x_type->name));47 fprintf(irp->f, "%s\n", buf_ptr(&const_instruction->base.static_value.data.x_type->name));
48 break;48 break;
49 case TypeTableEntryIdInt:
50 {
51 BigNum *bignum = &const_instruction->base.static_value.data.x_bignum;
52 assert(bignum->kind == BigNumKindInt);
53 const char *negative_str = bignum->is_negative ? "-" : "";
54 fprintf(irp->f, "%s%llu\n", negative_str, bignum->data.x_uint);
55 }
56 break;
49 case TypeTableEntryIdVar:57 case TypeTableEntryIdVar:
50 case TypeTableEntryIdBool:58 case TypeTableEntryIdBool:
51 case TypeTableEntryIdUnreachable:59 case TypeTableEntryIdUnreachable:
52 case TypeTableEntryIdInt:
53 case TypeTableEntryIdFloat:60 case TypeTableEntryIdFloat:
54 case TypeTableEntryIdPointer:61 case TypeTableEntryIdPointer:
55 case TypeTableEntryIdArray:62 case TypeTableEntryIdArray:
...@@ -127,6 +134,47 @@ static const char *ir_bin_op_id_str(IrBinOp op_id) {...@@ -127,6 +134,47 @@ static const char *ir_bin_op_id_str(IrBinOp op_id) {
127 zig_unreachable();134 zig_unreachable();
128}135}
129136
137static const char *ir_un_op_id_str(IrUnOp op_id) {
138 switch (op_id) {
139 case IrUnOpInvalid:
140 zig_unreachable();
141 case IrUnOpBoolNot:
142 return "!";
143 case IrUnOpBinNot:
144 return "~";
145 case IrUnOpNegation:
146 return "-";
147 case IrUnOpNegationWrap:
148 return "-%";
149 case IrUnOpAddressOf:
150 return "&";
151 case IrUnOpConstAddressOf:
152 return "&const";
153 case IrUnOpDereference:
154 return "*";
155 case IrUnOpMaybe:
156 return "?";
157 case IrUnOpError:
158 return "%";
159 case IrUnOpUnwrapError:
160 return "%%";
161 case IrUnOpUnwrapMaybe:
162 return "??";
163 case IrUnOpMaybeReturn:
164 return "?return";
165 case IrUnOpErrorReturn:
166 return "%return";
167 }
168 zig_unreachable();
169}
170
171static void ir_print_un_op(IrPrint *irp, IrInstructionUnOp *un_op_instruction) {
172 ir_print_prefix(irp, &un_op_instruction->base);
173 fprintf(irp->f, "%s #%zu\n",
174 ir_un_op_id_str(un_op_instruction->op_id),
175 un_op_instruction->value->debug_id);
176}
177
130static void ir_print_bin_op(IrPrint *irp, IrInstructionBinOp *bin_op_instruction) {178static void ir_print_bin_op(IrPrint *irp, IrInstructionBinOp *bin_op_instruction) {
131 ir_print_prefix(irp, &bin_op_instruction->base);179 ir_print_prefix(irp, &bin_op_instruction->base);
132 fprintf(irp->f, "#%zu %s #%zu\n",180 fprintf(irp->f, "#%zu %s #%zu\n",
...@@ -160,6 +208,47 @@ static void ir_print_call(IrPrint *irp, IrInstructionCall *call_instruction) {...@@ -160,6 +208,47 @@ static void ir_print_call(IrPrint *irp, IrInstructionCall *call_instruction) {
160 fprintf(irp->f, ")\n");208 fprintf(irp->f, ")\n");
161}209}
162210
211static void ir_print_builtin_call(IrPrint *irp, IrInstructionBuiltinCall *call_instruction) {
212 ir_print_prefix(irp, &call_instruction->base);
213 fprintf(irp->f, "@%s(", buf_ptr(&call_instruction->fn->name));
214 for (size_t i = 0; i < call_instruction->fn->param_count; i += 1) {
215 IrInstruction *arg = call_instruction->args[i];
216 if (i != 0)
217 fprintf(irp->f, ", ");
218 fprintf(irp->f, "#%zu", arg->debug_id);
219 }
220 fprintf(irp->f, ")\n");
221}
222
223
224static void ir_print_cond_br(IrPrint *irp, IrInstructionCondBr *cond_br_instruction) {
225 ir_print_prefix(irp, &cond_br_instruction->base);
226 fprintf(irp->f, "if #%zu then $%s_%zu else $%s_%zu\n",
227 cond_br_instruction->condition->debug_id,
228 cond_br_instruction->then_block->name_hint, cond_br_instruction->then_block->debug_id,
229 cond_br_instruction->else_block->name_hint, cond_br_instruction->else_block->debug_id);
230}
231
232static void ir_print_br(IrPrint *irp, IrInstructionBr *br_instruction) {
233 ir_print_prefix(irp, &br_instruction->base);
234 fprintf(irp->f, "goto $%s_%zu\n",
235 br_instruction->dest_block->name_hint, br_instruction->dest_block->debug_id);
236}
237
238static void ir_print_phi(IrPrint *irp, IrInstructionPhi *phi_instruction) {
239 ir_print_prefix(irp, &phi_instruction->base);
240 for (size_t i = 0; i < phi_instruction->incoming_count; i += 1) {
241 IrBasicBlock *incoming_block = phi_instruction->incoming_blocks[i];
242 IrInstruction *incoming_value = phi_instruction->incoming_values[i];
243 if (i != 0)
244 fprintf(irp->f, " ");
245 fprintf(irp->f, "$%s_%zu:#%zu",
246 incoming_block->name_hint, incoming_block->debug_id,
247 incoming_value->debug_id);
248 }
249 fprintf(irp->f, "\n");
250}
251
163static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {252static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
164 switch (instruction->id) {253 switch (instruction->id) {
165 case IrInstructionIdInvalid:254 case IrInstructionIdInvalid:
...@@ -182,11 +271,23 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -182,11 +271,23 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
182 case IrInstructionIdCall:271 case IrInstructionIdCall:
183 ir_print_call(irp, (IrInstructionCall *)instruction);272 ir_print_call(irp, (IrInstructionCall *)instruction);
184 break;273 break;
274 case IrInstructionIdUnOp:
275 ir_print_un_op(irp, (IrInstructionUnOp *)instruction);
276 break;
185 case IrInstructionIdCondBr:277 case IrInstructionIdCondBr:
186 case IrInstructionIdSwitchBr:278 ir_print_cond_br(irp, (IrInstructionCondBr *)instruction);
279 break;
280 case IrInstructionIdBr:
281 ir_print_br(irp, (IrInstructionBr *)instruction);
282 break;
283 case IrInstructionIdBuiltinCall:
284 ir_print_builtin_call(irp, (IrInstructionBuiltinCall *)instruction);
285 break;
187 case IrInstructionIdPhi:286 case IrInstructionIdPhi:
287 ir_print_phi(irp, (IrInstructionPhi *)instruction);
288 break;
289 case IrInstructionIdSwitchBr:
188 case IrInstructionIdStoreVar:290 case IrInstructionIdStoreVar:
189 case IrInstructionIdBuiltinCall:
190 zig_panic("TODO print more IR instructions");291 zig_panic("TODO print more IR instructions");
191 }292 }
192}293}
...@@ -200,6 +301,7 @@ void ir_print(FILE *f, IrExecutable *executable, int indent_size) {...@@ -200,6 +301,7 @@ void ir_print(FILE *f, IrExecutable *executable, int indent_size) {
200301
201 for (size_t bb_i = 0; bb_i < executable->basic_block_list.length; bb_i += 1) {302 for (size_t bb_i = 0; bb_i < executable->basic_block_list.length; bb_i += 1) {
202 IrBasicBlock *current_block = executable->basic_block_list.at(bb_i);303 IrBasicBlock *current_block = executable->basic_block_list.at(bb_i);
304 fprintf(irp->f, "%s_%zu:\n", current_block->name_hint, current_block->debug_id);
203 for (size_t instr_i = 0; instr_i < current_block->instruction_list.length; instr_i += 1) {305 for (size_t instr_i = 0; instr_i < current_block->instruction_list.length; instr_i += 1) {
204 IrInstruction *instruction = current_block->instruction_list.at(instr_i);306 IrInstruction *instruction = current_block->instruction_list.at(instr_i);
205 ir_print_instruction(irp, instruction);307 ir_print_instruction(irp, instruction);