authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-10-09 02:20:01-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-10-09 02:20:01-04:00
log77ae3442ef2dee1659ab5778f43c00026fd21dd9
tree3a9a3eae379ec2412608bc433d03df2a590e815b
parent07fe60ded1727d528d3ae36b892aa7c84262ed96

explicit casting works with IR


7 files changed, 835 insertions(+), 670 deletions(-)

src/all_types.hpp+5-2
...@@ -29,6 +29,7 @@ struct TypeStructField;...@@ -29,6 +29,7 @@ struct TypeStructField;
29struct CodeGen;29struct CodeGen;
30struct ConstExprValue;30struct ConstExprValue;
31struct IrInstruction;31struct IrInstruction;
32struct IrInstructionCast;
32struct IrBasicBlock;33struct IrBasicBlock;
3334
34struct IrExecutable {35struct IrExecutable {
...@@ -1121,7 +1122,7 @@ struct FnTableEntry {...@@ -1121,7 +1122,7 @@ struct FnTableEntry {
1121 AstNode *fn_test_set_node;1122 AstNode *fn_test_set_node;
1122 AstNode *fn_static_eval_set_node;1123 AstNode *fn_static_eval_set_node;
11231124
1124 ZigList<AstNode *> cast_alloca_list;1125 ZigList<IrInstructionCast *> cast_alloca_list;
1125 ZigList<StructValExprCodeGen *> struct_val_expr_alloca_list;1126 ZigList<StructValExprCodeGen *> struct_val_expr_alloca_list;
1126 ZigList<VariableTableEntry *> variable_list;1127 ZigList<VariableTableEntry *> variable_list;
1127 ZigList<AstNode *> goto_list;1128 ZigList<AstNode *> goto_list;
...@@ -1435,6 +1436,7 @@ struct IrInstruction {...@@ -1435,6 +1436,7 @@ struct IrInstruction {
1435 // if ref_count is zero, instruction can be omitted in codegen1436 // if ref_count is zero, instruction can be omitted in codegen
1436 size_t ref_count;1437 size_t ref_count;
1437 IrInstruction *other;1438 IrInstruction *other;
1439 ReturnKnowledge return_knowledge;
1438};1440};
14391441
1440struct IrInstructionCondBr {1442struct IrInstructionCondBr {
...@@ -1547,7 +1549,8 @@ struct IrInstructionCast {...@@ -1547,7 +1549,8 @@ struct IrInstructionCast {
15471549
1548 IrInstruction *value;1550 IrInstruction *value;
1549 IrInstruction *dest_type;1551 IrInstruction *dest_type;
1550 bool is_implicit;1552 CastOp cast_op;
1553 LLVMValueRef tmp_ptr;
1551};1554};
15521555
1553#endif1556#endif
src/analyze.cpp+11-290
...@@ -25,8 +25,6 @@ static VariableTableEntry *analyze_variable_declaration(CodeGen *g, ImportTableE...@@ -25,8 +25,6 @@ static VariableTableEntry *analyze_variable_declaration(CodeGen *g, ImportTableE
25 BlockContext *context, TypeTableEntry *expected_type, AstNode *node);25 BlockContext *context, TypeTableEntry *expected_type, AstNode *node);
26static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableEntry *struct_type);26static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableEntry *struct_type);
27static TypeTableEntry *unwrapped_node_type(AstNode *node);27static TypeTableEntry *unwrapped_node_type(AstNode *node);
28static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
29 AstNode *node);
30static TypeTableEntry *analyze_error_literal_expr(CodeGen *g, ImportTableEntry *import,28static TypeTableEntry *analyze_error_literal_expr(CodeGen *g, ImportTableEntry *import,
31 BlockContext *context, AstNode *node, Buf *err_name);29 BlockContext *context, AstNode *node, Buf *err_name);
32static TypeTableEntry *analyze_block_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,30static TypeTableEntry *analyze_block_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
...@@ -115,7 +113,7 @@ AstNode *first_executing_node(AstNode *node) {...@@ -115,7 +113,7 @@ AstNode *first_executing_node(AstNode *node) {
115 zig_unreachable();113 zig_unreachable();
116}114}
117115
118static void mark_impure_fn(CodeGen *g, BlockContext *context, AstNode *node) {116void mark_impure_fn(CodeGen *g, BlockContext *context, AstNode *node) {
119 if (!context->fn_entry) return;117 if (!context->fn_entry) return;
120 if (!context->fn_entry->is_pure) return;118 if (!context->fn_entry->is_pure) return;
121119
...@@ -261,11 +259,6 @@ uint64_t type_size(CodeGen *g, TypeTableEntry *type_entry) {...@@ -261,11 +259,6 @@ uint64_t type_size(CodeGen *g, TypeTableEntry *type_entry) {
261 }259 }
262}260}
263261
264static bool is_u8(TypeTableEntry *type) {
265 return type->id == TypeTableEntryIdInt &&
266 !type->data.integral.is_signed && type->data.integral.bit_count == 8;
267}
268
269static bool is_slice(TypeTableEntry *type) {262static bool is_slice(TypeTableEntry *type) {
270 return type->id == TypeTableEntryIdStruct && type->data.structure.is_slice;263 return type->id == TypeTableEntryIdStruct && type->data.structure.is_slice;
271}264}
...@@ -4466,30 +4459,7 @@ static TypeTableEntry *analyze_min_max_value(CodeGen *g, ImportTableEntry *impor...@@ -4466,30 +4459,7 @@ static TypeTableEntry *analyze_min_max_value(CodeGen *g, ImportTableEntry *impor
4466 }4459 }
4467}4460}
44684461
4469static TypeTableEntry *resolve_cast(CodeGen *g, BlockContext *context, AstNode *node,4462bool type_is_codegen_pointer(TypeTableEntry *type) {
4470 AstNode *expr_node, TypeTableEntry *wanted_type, CastOp op, bool need_alloca)
4471{
4472 node->data.fn_call_expr.cast_op = op;
4473
4474 ConstExprValue *other_val = &get_resolved_expr(expr_node)->const_val;
4475 TypeTableEntry *other_type = get_resolved_expr(expr_node)->type_entry;
4476 ConstExprValue *const_val = &get_resolved_expr(node)->const_val;
4477 if (other_val->ok) {
4478 eval_const_expr_implicit_cast(node->data.fn_call_expr.cast_op, other_val, other_type,
4479 const_val, wanted_type);
4480 }
4481
4482 if (need_alloca) {
4483 if (context->fn_entry) {
4484 context->fn_entry->cast_alloca_list.append(node);
4485 } else {
4486 assert(get_resolved_expr(node)->const_val.ok);
4487 }
4488 }
4489 return wanted_type;
4490}
4491
4492static bool type_is_codegen_pointer(TypeTableEntry *type) {
4493 if (type->id == TypeTableEntryIdPointer) return true;4463 if (type->id == TypeTableEntryIdPointer) return true;
4494 if (type->id == TypeTableEntryIdFn) return true;4464 if (type->id == TypeTableEntryIdFn) return true;
4495 if (type->id == TypeTableEntryIdMaybe) {4465 if (type->id == TypeTableEntryIdMaybe) {
...@@ -4499,256 +4469,6 @@ static bool type_is_codegen_pointer(TypeTableEntry *type) {...@@ -4499,256 +4469,6 @@ static bool type_is_codegen_pointer(TypeTableEntry *type) {
4499 return false;4469 return false;
4500}4470}
45014471
4502static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
4503 AstNode *node)
4504{
4505 assert(node->type == NodeTypeFnCallExpr);
4506
4507 AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr;
4508 size_t actual_param_count = node->data.fn_call_expr.params.length;
4509
4510 if (actual_param_count != 1) {
4511 add_node_error(g, fn_ref_expr, buf_sprintf("cast expression expects exactly one parameter"));
4512 return g->builtin_types.entry_invalid;
4513 }
4514
4515 AstNode *expr_node = node->data.fn_call_expr.params.at(0);
4516 TypeTableEntry *wanted_type = resolve_type(g, fn_ref_expr);
4517 TypeTableEntry *actual_type = analyze_expression(g, import, context, nullptr, expr_node);
4518 TypeTableEntry *wanted_type_canon = get_underlying_type(wanted_type);
4519 TypeTableEntry *actual_type_canon = get_underlying_type(actual_type);
4520
4521 if (wanted_type_canon->id == TypeTableEntryIdInvalid ||
4522 actual_type_canon->id == TypeTableEntryIdInvalid)
4523 {
4524 return g->builtin_types.entry_invalid;
4525 }
4526
4527 // explicit match or non-const to const
4528 if (types_match_const_cast_only(wanted_type, actual_type)) {
4529 return resolve_cast(g, context, node, expr_node, wanted_type, CastOpNoop, false);
4530 }
4531
4532 // explicit cast from bool to int
4533 if (wanted_type_canon->id == TypeTableEntryIdInt &&
4534 actual_type_canon->id == TypeTableEntryIdBool)
4535 {
4536 return resolve_cast(g, context, node, expr_node, wanted_type, CastOpBoolToInt, false);
4537 }
4538
4539 // explicit cast from pointer to isize or usize
4540 if ((wanted_type_canon == g->builtin_types.entry_isize || wanted_type_canon == g->builtin_types.entry_usize) &&
4541 type_is_codegen_pointer(actual_type_canon))
4542 {
4543 return resolve_cast(g, context, node, expr_node, wanted_type, CastOpPtrToInt, false);
4544 }
4545
4546
4547 // explicit cast from isize or usize to pointer
4548 if (wanted_type_canon->id == TypeTableEntryIdPointer &&
4549 (actual_type_canon == g->builtin_types.entry_isize || actual_type_canon == g->builtin_types.entry_usize))
4550 {
4551 return resolve_cast(g, context, node, expr_node, wanted_type, CastOpIntToPtr, false);
4552 }
4553
4554 // explicit widening or shortening cast
4555 if ((wanted_type_canon->id == TypeTableEntryIdInt &&
4556 actual_type_canon->id == TypeTableEntryIdInt) ||
4557 (wanted_type_canon->id == TypeTableEntryIdFloat &&
4558 actual_type_canon->id == TypeTableEntryIdFloat))
4559 {
4560 return resolve_cast(g, context, node, expr_node, wanted_type, CastOpWidenOrShorten, false);
4561 }
4562
4563 // explicit cast from int to float
4564 if (wanted_type_canon->id == TypeTableEntryIdFloat &&
4565 actual_type_canon->id == TypeTableEntryIdInt)
4566 {
4567 return resolve_cast(g, context, node, expr_node, wanted_type, CastOpIntToFloat, false);
4568 }
4569
4570 // explicit cast from float to int
4571 if (wanted_type_canon->id == TypeTableEntryIdInt &&
4572 actual_type_canon->id == TypeTableEntryIdFloat)
4573 {
4574 return resolve_cast(g, context, node, expr_node, wanted_type, CastOpFloatToInt, false);
4575 }
4576
4577 // explicit cast from array to slice
4578 if (is_slice(wanted_type) &&
4579 actual_type->id == TypeTableEntryIdArray &&
4580 types_match_const_cast_only(
4581 wanted_type->data.structure.fields[0].type_entry->data.pointer.child_type,
4582 actual_type->data.array.child_type))
4583 {
4584 return resolve_cast(g, context, node, expr_node, wanted_type, CastOpToUnknownSizeArray, true);
4585 }
4586
4587 // explicit cast from []T to []u8 or []u8 to []T
4588 if (is_slice(wanted_type) && is_slice(actual_type) &&
4589 (is_u8(wanted_type->data.structure.fields[0].type_entry->data.pointer.child_type) ||
4590 is_u8(actual_type->data.structure.fields[0].type_entry->data.pointer.child_type)) &&
4591 (wanted_type->data.structure.fields[0].type_entry->data.pointer.is_const ||
4592 !actual_type->data.structure.fields[0].type_entry->data.pointer.is_const))
4593 {
4594 mark_impure_fn(g, context, node);
4595 return resolve_cast(g, context, node, expr_node, wanted_type, CastOpResizeSlice, true);
4596 }
4597
4598 // explicit cast from [N]u8 to []T
4599 if (is_slice(wanted_type) &&
4600 actual_type->id == TypeTableEntryIdArray &&
4601 is_u8(actual_type->data.array.child_type))
4602 {
4603 mark_impure_fn(g, context, node);
4604 uint64_t child_type_size = type_size(g,
4605 wanted_type->data.structure.fields[0].type_entry->data.pointer.child_type);
4606 if (actual_type->data.array.len % child_type_size == 0) {
4607 return resolve_cast(g, context, node, expr_node, wanted_type, CastOpBytesToSlice, true);
4608 } else {
4609 add_node_error(g, node,
4610 buf_sprintf("unable to convert %s to %s: size mismatch",
4611 buf_ptr(&actual_type->name), buf_ptr(&wanted_type->name)));
4612 return g->builtin_types.entry_invalid;
4613 }
4614 }
4615
4616 // explicit cast from pointer to another pointer
4617 if ((actual_type->id == TypeTableEntryIdPointer || actual_type->id == TypeTableEntryIdFn) &&
4618 (wanted_type->id == TypeTableEntryIdPointer || wanted_type->id == TypeTableEntryIdFn))
4619 {
4620 return resolve_cast(g, context, node, expr_node, wanted_type, CastOpPointerReinterpret, false);
4621 }
4622
4623 // explicit cast from maybe pointer to another maybe pointer
4624 if (actual_type->id == TypeTableEntryIdMaybe &&
4625 (actual_type->data.maybe.child_type->id == TypeTableEntryIdPointer ||
4626 actual_type->data.maybe.child_type->id == TypeTableEntryIdFn) &&
4627 wanted_type->id == TypeTableEntryIdMaybe &&
4628 (wanted_type->data.maybe.child_type->id == TypeTableEntryIdPointer ||
4629 wanted_type->data.maybe.child_type->id == TypeTableEntryIdFn))
4630 {
4631 return resolve_cast(g, context, node, expr_node, wanted_type, CastOpPointerReinterpret, false);
4632 }
4633
4634 // explicit cast from child type of maybe type to maybe type
4635 if (wanted_type->id == TypeTableEntryIdMaybe) {
4636 if (types_match_const_cast_only(wanted_type->data.maybe.child_type, actual_type)) {
4637 get_resolved_expr(node)->return_knowledge = ReturnKnowledgeKnownNonNull;
4638 return resolve_cast(g, context, node, expr_node, wanted_type, CastOpMaybeWrap, true);
4639 } else if (actual_type->id == TypeTableEntryIdNumLitInt ||
4640 actual_type->id == TypeTableEntryIdNumLitFloat)
4641 {
4642 if (num_lit_fits_in_other_type(g, expr_node, wanted_type->data.maybe.child_type)) {
4643 get_resolved_expr(node)->return_knowledge = ReturnKnowledgeKnownNonNull;
4644 return resolve_cast(g, context, node, expr_node, wanted_type, CastOpMaybeWrap, true);
4645 } else {
4646 return g->builtin_types.entry_invalid;
4647 }
4648 }
4649 }
4650
4651 // explicit cast from null literal to maybe type
4652 if (wanted_type->id == TypeTableEntryIdMaybe &&
4653 actual_type->id == TypeTableEntryIdNullLit)
4654 {
4655 get_resolved_expr(node)->return_knowledge = ReturnKnowledgeKnownNull;
4656 return resolve_cast(g, context, node, expr_node, wanted_type, CastOpNullToMaybe, true);
4657 }
4658
4659 // explicit cast from child type of error type to error type
4660 if (wanted_type->id == TypeTableEntryIdErrorUnion) {
4661 if (types_match_const_cast_only(wanted_type->data.error.child_type, actual_type)) {
4662 get_resolved_expr(node)->return_knowledge = ReturnKnowledgeKnownNonError;
4663 return resolve_cast(g, context, node, expr_node, wanted_type, CastOpErrorWrap, true);
4664 } else if (actual_type->id == TypeTableEntryIdNumLitInt ||
4665 actual_type->id == TypeTableEntryIdNumLitFloat)
4666 {
4667 if (num_lit_fits_in_other_type(g, expr_node, wanted_type->data.error.child_type)) {
4668 get_resolved_expr(node)->return_knowledge = ReturnKnowledgeKnownNonError;
4669 return resolve_cast(g, context, node, expr_node, wanted_type, CastOpErrorWrap, true);
4670 } else {
4671 return g->builtin_types.entry_invalid;
4672 }
4673 }
4674 }
4675
4676 // explicit cast from pure error to error union type
4677 if (wanted_type->id == TypeTableEntryIdErrorUnion &&
4678 actual_type->id == TypeTableEntryIdPureError)
4679 {
4680 get_resolved_expr(node)->return_knowledge = ReturnKnowledgeKnownError;
4681 return resolve_cast(g, context, node, expr_node, wanted_type, CastOpPureErrorWrap, false);
4682 }
4683
4684 // explicit cast from number literal to another type
4685 if (actual_type->id == TypeTableEntryIdNumLitFloat ||
4686 actual_type->id == TypeTableEntryIdNumLitInt)
4687 {
4688 if (num_lit_fits_in_other_type(g, expr_node, wanted_type_canon)) {
4689 CastOp op;
4690 if ((actual_type->id == TypeTableEntryIdNumLitFloat &&
4691 wanted_type_canon->id == TypeTableEntryIdFloat) ||
4692 (actual_type->id == TypeTableEntryIdNumLitInt &&
4693 wanted_type_canon->id == TypeTableEntryIdInt))
4694 {
4695 op = CastOpNoop;
4696 } else if (wanted_type_canon->id == TypeTableEntryIdInt) {
4697 op = CastOpFloatToInt;
4698 } else if (wanted_type_canon->id == TypeTableEntryIdFloat) {
4699 op = CastOpIntToFloat;
4700 } else {
4701 zig_unreachable();
4702 }
4703 return resolve_cast(g, context, node, expr_node, wanted_type, op, false);
4704 } else {
4705 return g->builtin_types.entry_invalid;
4706 }
4707 }
4708
4709 // explicit cast from %void to integer type which can fit it
4710 bool actual_type_is_void_err = actual_type->id == TypeTableEntryIdErrorUnion &&
4711 !type_has_bits(actual_type->data.error.child_type);
4712 bool actual_type_is_pure_err = actual_type->id == TypeTableEntryIdPureError;
4713 if ((actual_type_is_void_err || actual_type_is_pure_err) &&
4714 wanted_type->id == TypeTableEntryIdInt)
4715 {
4716 BigNum bn;
4717 bignum_init_unsigned(&bn, g->error_decls.length);
4718 if (bignum_fits_in_bits(&bn, wanted_type->data.integral.bit_count,
4719 wanted_type->data.integral.is_signed))
4720 {
4721 return resolve_cast(g, context, node, expr_node, wanted_type, CastOpErrToInt, false);
4722 } else {
4723 add_node_error(g, node,
4724 buf_sprintf("too many error values to fit in '%s'", buf_ptr(&wanted_type->name)));
4725 return g->builtin_types.entry_invalid;
4726 }
4727 }
4728
4729 // explicit cast from integer to enum type with no payload
4730 if (actual_type->id == TypeTableEntryIdInt &&
4731 wanted_type->id == TypeTableEntryIdEnum &&
4732 wanted_type->data.enumeration.gen_field_count == 0)
4733 {
4734 return resolve_cast(g, context, node, expr_node, wanted_type, CastOpIntToEnum, false);
4735 }
4736
4737 // explicit cast from enum type with no payload to integer
4738 if (wanted_type->id == TypeTableEntryIdInt &&
4739 actual_type->id == TypeTableEntryIdEnum &&
4740 actual_type->data.enumeration.gen_field_count == 0)
4741 {
4742 return resolve_cast(g, context, node, expr_node, wanted_type, CastOpEnumToInt, false);
4743 }
4744
4745 add_node_error(g, node,
4746 buf_sprintf("invalid cast from type '%s' to '%s'",
4747 buf_ptr(&actual_type->name),
4748 buf_ptr(&wanted_type->name)));
4749 return g->builtin_types.entry_invalid;
4750}
4751
4752static TypeTableEntry *analyze_import(CodeGen *g, ImportTableEntry *import, BlockContext *context,4472static TypeTableEntry *analyze_import(CodeGen *g, ImportTableEntry *import, BlockContext *context,
4753 AstNode *node)4473 AstNode *node)
4754{4474{
...@@ -5866,13 +5586,14 @@ static TypeTableEntry *analyze_fn_call_ptr(CodeGen *g, ImportTableEntry *import,...@@ -5866,13 +5586,14 @@ static TypeTableEntry *analyze_fn_call_ptr(CodeGen *g, ImportTableEntry *import,
5866 }5586 }
5867 }5587 }
58685588
5869 if (handle_is_ptr(return_type)) {5589 // TODO
5870 if (context->fn_entry) {5590 //if (handle_is_ptr(return_type)) {
5871 context->fn_entry->cast_alloca_list.append(node);5591 // if (context->fn_entry) {
5872 } else if (!result_val->ok) {5592 // context->fn_entry->cast_alloca_list.append(node);
5873 add_node_error(g, node, buf_sprintf("unable to evaluate constant expression"));5593 // } else if (!result_val->ok) {
5874 }5594 // add_node_error(g, node, buf_sprintf("unable to evaluate constant expression"));
5875 }5595 // }
5596 //}
58765597
5877 return return_type;5598 return return_type;
5878}5599}
...@@ -6110,7 +5831,7 @@ static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import...@@ -6110,7 +5831,7 @@ static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import
61105831
6111 if (const_val->ok) {5832 if (const_val->ok) {
6112 if (invoke_type_entry->id == TypeTableEntryIdMetaType) {5833 if (invoke_type_entry->id == TypeTableEntryIdMetaType) {
6113 return analyze_cast_expr(g, import, context, node);5834 zig_unreachable();
6114 } else if (invoke_type_entry->id == TypeTableEntryIdFn) {5835 } else if (invoke_type_entry->id == TypeTableEntryIdFn) {
6115 AstNode *struct_node;5836 AstNode *struct_node;
6116 if (fn_ref_expr->type == NodeTypeFieldAccessExpr &&5837 if (fn_ref_expr->type == NodeTypeFieldAccessExpr &&
src/analyze.hpp+4
...@@ -49,10 +49,14 @@ TypeTableEntry *resolve_peer_type_compatibility(CodeGen *g, ImportTableEntry *im...@@ -49,10 +49,14 @@ TypeTableEntry *resolve_peer_type_compatibility(CodeGen *g, ImportTableEntry *im
49 BlockContext *block_context, AstNode *parent_source_node,49 BlockContext *block_context, AstNode *parent_source_node,
50 AstNode **child_nodes, TypeTableEntry **child_types, size_t child_count);50 AstNode **child_nodes, TypeTableEntry **child_types, size_t child_count);
5151
52
53
52bool types_match_const_cast_only(TypeTableEntry *expected_type, TypeTableEntry *actual_type);54bool types_match_const_cast_only(TypeTableEntry *expected_type, TypeTableEntry *actual_type);
53VariableTableEntry *find_variable(CodeGen *g, BlockContext *orig_context, Buf *name);55VariableTableEntry *find_variable(CodeGen *g, BlockContext *orig_context, Buf *name);
54AstNode *find_decl(BlockContext *context, Buf *name);56AstNode *find_decl(BlockContext *context, Buf *name);
55void resolve_top_level_decl(CodeGen *g, AstNode *node, bool pointer_only);57void resolve_top_level_decl(CodeGen *g, AstNode *node, bool pointer_only);
56TopLevelDecl *get_as_top_level_decl(AstNode *node);58TopLevelDecl *get_as_top_level_decl(AstNode *node);
59void mark_impure_fn(CodeGen *g, BlockContext *context, AstNode *node);
60bool type_is_codegen_pointer(TypeTableEntry *type);
5761
58#endif62#endif
src/codegen.cpp+255-359
...@@ -344,11 +344,10 @@ static LLVMValueRef get_int_builtin_fn(CodeGen *g, TypeTableEntry *int_type, Bui...@@ -344,11 +344,10 @@ static LLVMValueRef get_int_builtin_fn(CodeGen *g, TypeTableEntry *int_type, Bui
344 return *fn;344 return *fn;
345}345}
346346
347static LLVMValueRef get_handle_value(CodeGen *g, AstNode *source_node, LLVMValueRef ptr, TypeTableEntry *type) {347static LLVMValueRef get_handle_value(CodeGen *g, LLVMValueRef ptr, TypeTableEntry *type) {
348 if (handle_is_ptr(type)) {348 if (handle_is_ptr(type)) {
349 return ptr;349 return ptr;
350 } else {350 } else {
351 set_debug_source_node(g, source_node);
352 return LLVMBuildLoad(g->builder, ptr, "");351 return LLVMBuildLoad(g->builder, ptr, "");
353 }352 }
354}353}
...@@ -378,7 +377,7 @@ static void gen_debug_safety_crash(CodeGen *g) {...@@ -378,7 +377,7 @@ static void gen_debug_safety_crash(CodeGen *g) {
378 LLVMBuildUnreachable(g->builder);377 LLVMBuildUnreachable(g->builder);
379}378}
380379
381static void add_bounds_check(CodeGen *g, AstNode *source_node, LLVMValueRef target_val,380static void add_bounds_check(CodeGen *g, LLVMValueRef target_val,
382 LLVMIntPredicate lower_pred, LLVMValueRef lower_value,381 LLVMIntPredicate lower_pred, LLVMValueRef lower_value,
383 LLVMIntPredicate upper_pred, LLVMValueRef upper_value)382 LLVMIntPredicate upper_pred, LLVMValueRef upper_value)
384{383{
...@@ -391,8 +390,6 @@ static void add_bounds_check(CodeGen *g, AstNode *source_node, LLVMValueRef targ...@@ -391,8 +390,6 @@ static void add_bounds_check(CodeGen *g, AstNode *source_node, LLVMValueRef targ
391 upper_value = nullptr;390 upper_value = nullptr;
392 }391 }
393392
394 set_debug_source_node(g, source_node);
395
396 LLVMBasicBlockRef bounds_check_fail_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "BoundsCheckFail");393 LLVMBasicBlockRef bounds_check_fail_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "BoundsCheckFail");
397 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "BoundsCheckOk");394 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "BoundsCheckOk");
398 LLVMBasicBlockRef lower_ok_block = upper_value ?395 LLVMBasicBlockRef lower_ok_block = upper_value ?
...@@ -425,12 +422,11 @@ static LLVMValueRef gen_err_name(CodeGen *g, AstNode *node) {...@@ -425,12 +422,11 @@ static LLVMValueRef gen_err_name(CodeGen *g, AstNode *node) {
425422
426 AstNode *err_val_node = node->data.fn_call_expr.params.at(0);423 AstNode *err_val_node = node->data.fn_call_expr.params.at(0);
427 LLVMValueRef err_val = gen_expr(g, err_val_node);424 LLVMValueRef err_val = gen_expr(g, err_val_node);
428 set_debug_source_node(g, node);
429425
430 if (want_debug_safety(g, node)) {426 if (want_debug_safety(g, node)) {
431 LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(err_val));427 LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(err_val));
432 LLVMValueRef end_val = LLVMConstInt(LLVMTypeOf(err_val), g->error_decls.length, false);428 LLVMValueRef end_val = LLVMConstInt(LLVMTypeOf(err_val), g->error_decls.length, false);
433 add_bounds_check(g, node, err_val, LLVMIntNE, zero, LLVMIntULT, end_val);429 add_bounds_check(g, err_val, LLVMIntNE, zero, LLVMIntULT, end_val);
434 }430 }
435431
436 LLVMValueRef indices[] = {432 LLVMValueRef indices[] = {
...@@ -514,15 +510,12 @@ static LLVMValueRef gen_truncate(CodeGen *g, AstNode *node) {...@@ -514,15 +510,12 @@ static LLVMValueRef gen_truncate(CodeGen *g, AstNode *node) {
514510
515 LLVMValueRef src_val = gen_expr(g, src_node);511 LLVMValueRef src_val = gen_expr(g, src_node);
516512
517 set_debug_source_node(g, node);
518 return LLVMBuildTrunc(g->builder, src_val, dest_type->type_ref, "");513 return LLVMBuildTrunc(g->builder, src_val, dest_type->type_ref, "");
519}514}
520515
521static LLVMValueRef gen_unreachable(CodeGen *g, AstNode *node) {516static LLVMValueRef gen_unreachable(CodeGen *g, AstNode *node) {
522 assert(node->type == NodeTypeFnCallExpr);517 assert(node->type == NodeTypeFnCallExpr);
523518
524 set_debug_source_node(g, node);
525
526 if (want_debug_safety(g, node) || g->is_test_build) {519 if (want_debug_safety(g, node) || g->is_test_build) {
527 gen_debug_safety_crash(g);520 gen_debug_safety_crash(g);
528 } else {521 } else {
...@@ -545,7 +538,6 @@ static LLVMValueRef gen_shl_with_overflow(CodeGen *g, AstNode *node) {...@@ -545,7 +538,6 @@ static LLVMValueRef gen_shl_with_overflow(CodeGen *g, AstNode *node) {
545 LLVMValueRef val2 = gen_expr(g, node->data.fn_call_expr.params.at(2));538 LLVMValueRef val2 = gen_expr(g, node->data.fn_call_expr.params.at(2));
546 LLVMValueRef ptr_result = gen_expr(g, node->data.fn_call_expr.params.at(3));539 LLVMValueRef ptr_result = gen_expr(g, node->data.fn_call_expr.params.at(3));
547540
548 set_debug_source_node(g, node);
549 LLVMValueRef result = LLVMBuildShl(g->builder, val1, val2, "");541 LLVMValueRef result = LLVMBuildShl(g->builder, val1, val2, "");
550 LLVMValueRef orig_val;542 LLVMValueRef orig_val;
551 if (int_type->data.integral.is_signed) {543 if (int_type->data.integral.is_signed) {
...@@ -590,7 +582,6 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {...@@ -590,7 +582,6 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {
590 operand,582 operand,
591 LLVMConstNull(LLVMInt1Type()),583 LLVMConstNull(LLVMInt1Type()),
592 };584 };
593 set_debug_source_node(g, node);
594 return LLVMBuildCall(g->builder, fn_val, params, 2, "");585 return LLVMBuildCall(g->builder, fn_val, params, 2, "");
595 }586 }
596 case BuiltinFnIdAddWithOverflow:587 case BuiltinFnIdAddWithOverflow:
...@@ -622,7 +613,6 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {...@@ -622,7 +613,6 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {
622 op2,613 op2,
623 };614 };
624615
625 set_debug_source_node(g, node);
626 LLVMValueRef result_struct = LLVMBuildCall(g->builder, fn_val, params, 2, "");616 LLVMValueRef result_struct = LLVMBuildCall(g->builder, fn_val, params, 2, "");
627 LLVMValueRef result = LLVMBuildExtractValue(g->builder, result_struct, 0, "");617 LLVMValueRef result = LLVMBuildExtractValue(g->builder, result_struct, 0, "");
628 LLVMValueRef overflow_bit = LLVMBuildExtractValue(g->builder, result_struct, 1, "");618 LLVMValueRef overflow_bit = LLVMBuildExtractValue(g->builder, result_struct, 1, "");
...@@ -646,7 +636,6 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {...@@ -646,7 +636,6 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {
646636
647 LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);637 LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
648638
649 set_debug_source_node(g, node);
650 LLVMValueRef dest_ptr_casted = LLVMBuildBitCast(g->builder, dest_ptr, ptr_u8, "");639 LLVMValueRef dest_ptr_casted = LLVMBuildBitCast(g->builder, dest_ptr, ptr_u8, "");
651 LLVMValueRef src_ptr_casted = LLVMBuildBitCast(g->builder, src_ptr, ptr_u8, "");640 LLVMValueRef src_ptr_casted = LLVMBuildBitCast(g->builder, src_ptr, ptr_u8, "");
652641
...@@ -677,7 +666,6 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {...@@ -677,7 +666,6 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {
677666
678 LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);667 LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
679668
680 set_debug_source_node(g, node);
681 LLVMValueRef dest_ptr_casted = LLVMBuildBitCast(g->builder, dest_ptr, ptr_u8, "");669 LLVMValueRef dest_ptr_casted = LLVMBuildBitCast(g->builder, dest_ptr, ptr_u8, "");
682670
683 uint64_t align_in_bytes = get_memcpy_align(g, dest_type->data.pointer.child_type);671 uint64_t align_in_bytes = get_memcpy_align(g, dest_type->data.pointer.child_type);
...@@ -707,13 +695,11 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {...@@ -707,13 +695,11 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {
707 case BuiltinFnIdErrName:695 case BuiltinFnIdErrName:
708 return gen_err_name(g, node);696 return gen_err_name(g, node);
709 case BuiltinFnIdBreakpoint:697 case BuiltinFnIdBreakpoint:
710 set_debug_source_node(g, node);
711 return LLVMBuildCall(g->builder, g->trap_fn_val, nullptr, 0, "");698 return LLVMBuildCall(g->builder, g->trap_fn_val, nullptr, 0, "");
712 case BuiltinFnIdFrameAddress:699 case BuiltinFnIdFrameAddress:
713 case BuiltinFnIdReturnAddress:700 case BuiltinFnIdReturnAddress:
714 {701 {
715 LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_i32->type_ref);702 LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_i32->type_ref);
716 set_debug_source_node(g, node);
717 return LLVMBuildCall(g->builder, builtin_fn->fn_val, &zero, 1, "");703 return LLVMBuildCall(g->builder, builtin_fn->fn_val, &zero, 1, "");
718 }704 }
719 case BuiltinFnIdCmpExchange:705 case BuiltinFnIdCmpExchange:
...@@ -760,7 +746,6 @@ static LLVMValueRef gen_enum_value_expr(CodeGen *g, AstNode *node, TypeTableEntr...@@ -760,7 +746,6 @@ static LLVMValueRef gen_enum_value_expr(CodeGen *g, AstNode *node, TypeTableEntr
760 LLVMValueRef tmp_struct_ptr = node->data.field_access_expr.resolved_struct_val_expr.ptr;746 LLVMValueRef tmp_struct_ptr = node->data.field_access_expr.resolved_struct_val_expr.ptr;
761747
762 // populate the new tag value748 // populate the new tag value
763 set_debug_source_node(g, node);
764 LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, 0, "");749 LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, 0, "");
765 LLVMBuildStore(g->builder, tag_value, tag_field_ptr);750 LLVMBuildStore(g->builder, tag_value, tag_field_ptr);
766751
...@@ -804,7 +789,6 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, AstNode *source_node, TypeT...@@ -804,7 +789,6 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, AstNode *source_node, TypeT
804 !wanted_type->data.integral.is_signed && actual_type->data.integral.is_signed &&789 !wanted_type->data.integral.is_signed && actual_type->data.integral.is_signed &&
805 want_debug_safety(g, source_node))790 want_debug_safety(g, source_node))
806 {791 {
807 set_debug_source_node(g, source_node);
808 LLVMValueRef zero = LLVMConstNull(actual_type->type_ref);792 LLVMValueRef zero = LLVMConstNull(actual_type->type_ref);
809 LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntSGE, expr_val, zero, "");793 LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntSGE, expr_val, zero, "");
810794
...@@ -822,14 +806,11 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, AstNode *source_node, TypeT...@@ -822,14 +806,11 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, AstNode *source_node, TypeT
822 return expr_val;806 return expr_val;
823 } else if (actual_bits < wanted_bits) {807 } else if (actual_bits < wanted_bits) {
824 if (actual_type->id == TypeTableEntryIdFloat) {808 if (actual_type->id == TypeTableEntryIdFloat) {
825 set_debug_source_node(g, source_node);
826 return LLVMBuildFPExt(g->builder, expr_val, wanted_type->type_ref, "");809 return LLVMBuildFPExt(g->builder, expr_val, wanted_type->type_ref, "");
827 } else if (actual_type->id == TypeTableEntryIdInt) {810 } else if (actual_type->id == TypeTableEntryIdInt) {
828 if (actual_type->data.integral.is_signed) {811 if (actual_type->data.integral.is_signed) {
829 set_debug_source_node(g, source_node);
830 return LLVMBuildSExt(g->builder, expr_val, wanted_type->type_ref, "");812 return LLVMBuildSExt(g->builder, expr_val, wanted_type->type_ref, "");
831 } else {813 } else {
832 set_debug_source_node(g, source_node);
833 return LLVMBuildZExt(g->builder, expr_val, wanted_type->type_ref, "");814 return LLVMBuildZExt(g->builder, expr_val, wanted_type->type_ref, "");
834 }815 }
835 } else {816 } else {
...@@ -837,10 +818,8 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, AstNode *source_node, TypeT...@@ -837,10 +818,8 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, AstNode *source_node, TypeT
837 }818 }
838 } else if (actual_bits > wanted_bits) {819 } else if (actual_bits > wanted_bits) {
839 if (actual_type->id == TypeTableEntryIdFloat) {820 if (actual_type->id == TypeTableEntryIdFloat) {
840 set_debug_source_node(g, source_node);
841 return LLVMBuildFPTrunc(g->builder, expr_val, wanted_type->type_ref, "");821 return LLVMBuildFPTrunc(g->builder, expr_val, wanted_type->type_ref, "");
842 } else if (actual_type->id == TypeTableEntryIdInt) {822 } else if (actual_type->id == TypeTableEntryIdInt) {
843 set_debug_source_node(g, source_node);
844 LLVMValueRef trunc_val = LLVMBuildTrunc(g->builder, expr_val, wanted_type->type_ref, "");823 LLVMValueRef trunc_val = LLVMBuildTrunc(g->builder, expr_val, wanted_type->type_ref, "");
845 if (!want_debug_safety(g, source_node)) {824 if (!want_debug_safety(g, source_node)) {
846 return trunc_val;825 return trunc_val;
...@@ -869,256 +848,11 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, AstNode *source_node, TypeT...@@ -869,256 +848,11 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, AstNode *source_node, TypeT
869 }848 }
870}849}
871850
872static LLVMValueRef gen_cast_expr(CodeGen *g, AstNode *node) {
873 assert(node->type == NodeTypeFnCallExpr);
874
875 AstNode *expr_node = node->data.fn_call_expr.params.at(0);
876
877 LLVMValueRef expr_val = gen_expr(g, expr_node);
878
879 TypeTableEntry *actual_type = get_expr_type(expr_node);
880 TypeTableEntry *wanted_type = get_expr_type(node);
881
882 AstNodeFnCallExpr *cast_expr = &node->data.fn_call_expr;
883
884 switch (cast_expr->cast_op) {
885 case CastOpNoCast:
886 zig_unreachable();
887 case CastOpNoop:
888 return expr_val;
889 case CastOpErrToInt:
890 assert(actual_type->id == TypeTableEntryIdErrorUnion);
891 if (!type_has_bits(actual_type->data.error.child_type)) {
892 return gen_widen_or_shorten(g, node, g->err_tag_type, wanted_type, expr_val);
893 } else {
894 zig_panic("TODO");
895 }
896 case CastOpMaybeWrap:
897 {
898 assert(cast_expr->tmp_ptr);
899 assert(wanted_type->id == TypeTableEntryIdMaybe);
900 assert(actual_type);
901
902 TypeTableEntry *child_type = wanted_type->data.maybe.child_type;
903
904 if (child_type->id == TypeTableEntryIdPointer ||
905 child_type->id == TypeTableEntryIdFn)
906 {
907 return expr_val;
908 } else {
909 set_debug_source_node(g, node);
910 LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, cast_expr->tmp_ptr, 0, "");
911 gen_assign_raw(g, node, BinOpTypeAssign,
912 val_ptr, expr_val, child_type, actual_type);
913
914 set_debug_source_node(g, node);
915 LLVMValueRef maybe_ptr = LLVMBuildStructGEP(g->builder, cast_expr->tmp_ptr, 1, "");
916 LLVMBuildStore(g->builder, LLVMConstAllOnes(LLVMInt1Type()), maybe_ptr);
917 }
918
919 return cast_expr->tmp_ptr;
920 }
921 case CastOpNullToMaybe:
922 // handled by constant expression evaluator
923 zig_unreachable();
924 case CastOpErrorWrap:
925 {
926 assert(wanted_type->id == TypeTableEntryIdErrorUnion);
927 TypeTableEntry *child_type = wanted_type->data.error.child_type;
928 LLVMValueRef ok_err_val = LLVMConstNull(g->err_tag_type->type_ref);
929
930 if (!type_has_bits(child_type)) {
931 return ok_err_val;
932 } else {
933 assert(cast_expr->tmp_ptr);
934 assert(wanted_type->id == TypeTableEntryIdErrorUnion);
935 assert(actual_type);
936
937 set_debug_source_node(g, node);
938 LLVMValueRef err_tag_ptr = LLVMBuildStructGEP(g->builder, cast_expr->tmp_ptr, 0, "");
939 LLVMBuildStore(g->builder, ok_err_val, err_tag_ptr);
940
941 LLVMValueRef payload_ptr = LLVMBuildStructGEP(g->builder, cast_expr->tmp_ptr, 1, "");
942 gen_assign_raw(g, node, BinOpTypeAssign,
943 payload_ptr, expr_val, child_type, actual_type);
944
945 return cast_expr->tmp_ptr;
946 }
947 }
948 case CastOpPureErrorWrap:
949 assert(wanted_type->id == TypeTableEntryIdErrorUnion);
950
951 if (!type_has_bits(wanted_type->data.error.child_type)) {
952 return expr_val;
953 } else {
954 zig_panic("TODO");
955 }
956 case CastOpPtrToInt:
957 set_debug_source_node(g, node);
958 return LLVMBuildPtrToInt(g->builder, expr_val, wanted_type->type_ref, "");
959 case CastOpIntToPtr:
960 set_debug_source_node(g, node);
961 return LLVMBuildIntToPtr(g->builder, expr_val, wanted_type->type_ref, "");
962 case CastOpPointerReinterpret:
963 set_debug_source_node(g, node);
964 return LLVMBuildBitCast(g->builder, expr_val, wanted_type->type_ref, "");
965 case CastOpWidenOrShorten:
966 return gen_widen_or_shorten(g, node, actual_type, wanted_type, expr_val);
967 case CastOpToUnknownSizeArray:
968 {
969 assert(cast_expr->tmp_ptr);
970 assert(wanted_type->id == TypeTableEntryIdStruct);
971 assert(wanted_type->data.structure.is_slice);
972
973 TypeTableEntry *pointer_type = wanted_type->data.structure.fields[0].type_entry;
974
975 set_debug_source_node(g, node);
976
977 size_t ptr_index = wanted_type->data.structure.fields[0].gen_index;
978 if (ptr_index != SIZE_MAX) {
979 LLVMValueRef ptr_ptr = LLVMBuildStructGEP(g->builder, cast_expr->tmp_ptr, ptr_index, "");
980 LLVMValueRef expr_bitcast = LLVMBuildBitCast(g->builder, expr_val, pointer_type->type_ref, "");
981 LLVMBuildStore(g->builder, expr_bitcast, ptr_ptr);
982 }
983
984 size_t len_index = wanted_type->data.structure.fields[1].gen_index;
985 LLVMValueRef len_ptr = LLVMBuildStructGEP(g->builder, cast_expr->tmp_ptr, len_index, "");
986 LLVMValueRef len_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref,
987 actual_type->data.array.len, false);
988 LLVMBuildStore(g->builder, len_val, len_ptr);
989
990 return cast_expr->tmp_ptr;
991 }
992 case CastOpResizeSlice:
993 {
994 assert(cast_expr->tmp_ptr);
995 assert(wanted_type->id == TypeTableEntryIdStruct);
996 assert(wanted_type->data.structure.is_slice);
997 assert(actual_type->id == TypeTableEntryIdStruct);
998 assert(actual_type->data.structure.is_slice);
999
1000 TypeTableEntry *actual_pointer_type = actual_type->data.structure.fields[0].type_entry;
1001 TypeTableEntry *actual_child_type = actual_pointer_type->data.pointer.child_type;
1002 TypeTableEntry *wanted_pointer_type = wanted_type->data.structure.fields[0].type_entry;
1003 TypeTableEntry *wanted_child_type = wanted_pointer_type->data.pointer.child_type;
1004
1005 set_debug_source_node(g, node);
1006
1007 size_t actual_ptr_index = actual_type->data.structure.fields[0].gen_index;
1008 size_t actual_len_index = actual_type->data.structure.fields[1].gen_index;
1009 size_t wanted_ptr_index = wanted_type->data.structure.fields[0].gen_index;
1010 size_t wanted_len_index = wanted_type->data.structure.fields[1].gen_index;
1011
1012 LLVMValueRef src_ptr_ptr = LLVMBuildStructGEP(g->builder, expr_val, actual_ptr_index, "");
1013 LLVMValueRef src_ptr = LLVMBuildLoad(g->builder, src_ptr_ptr, "");
1014 LLVMValueRef src_ptr_casted = LLVMBuildBitCast(g->builder, src_ptr,
1015 wanted_type->data.structure.fields[0].type_entry->type_ref, "");
1016 LLVMValueRef dest_ptr_ptr = LLVMBuildStructGEP(g->builder, cast_expr->tmp_ptr,
1017 wanted_ptr_index, "");
1018 LLVMBuildStore(g->builder, src_ptr_casted, dest_ptr_ptr);
1019
1020 LLVMValueRef src_len_ptr = LLVMBuildStructGEP(g->builder, expr_val, actual_len_index, "");
1021 LLVMValueRef src_len = LLVMBuildLoad(g->builder, src_len_ptr, "");
1022 uint64_t src_size = type_size(g, actual_child_type);
1023 uint64_t dest_size = type_size(g, wanted_child_type);
1024
1025 LLVMValueRef new_len;
1026 if (dest_size == 1) {
1027 LLVMValueRef src_size_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref, src_size, false);
1028 new_len = LLVMBuildMul(g->builder, src_len, src_size_val, "");
1029 } else if (src_size == 1) {
1030 LLVMValueRef dest_size_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref, dest_size, false);
1031 if (want_debug_safety(g, node)) {
1032 LLVMValueRef remainder_val = LLVMBuildURem(g->builder, src_len, dest_size_val, "");
1033 LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_usize->type_ref);
1034 LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, remainder_val, zero, "");
1035 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "SliceWidenOk");
1036 LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "SliceWidenFail");
1037 LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block);
1038
1039 LLVMPositionBuilderAtEnd(g->builder, fail_block);
1040 gen_debug_safety_crash(g);
1041
1042 LLVMPositionBuilderAtEnd(g->builder, ok_block);
1043 }
1044 new_len = ZigLLVMBuildExactUDiv(g->builder, src_len, dest_size_val, "");
1045 } else {
1046 zig_unreachable();
1047 }
1048
1049 LLVMValueRef dest_len_ptr = LLVMBuildStructGEP(g->builder, cast_expr->tmp_ptr,
1050 wanted_len_index, "");
1051 LLVMBuildStore(g->builder, new_len, dest_len_ptr);
1052
1053
1054 return cast_expr->tmp_ptr;
1055 }
1056 case CastOpBytesToSlice:
1057 {
1058 assert(cast_expr->tmp_ptr);
1059 assert(wanted_type->id == TypeTableEntryIdStruct);
1060 assert(wanted_type->data.structure.is_slice);
1061 assert(actual_type->id == TypeTableEntryIdArray);
1062
1063 TypeTableEntry *wanted_pointer_type = wanted_type->data.structure.fields[0].type_entry;
1064 TypeTableEntry *wanted_child_type = wanted_pointer_type->data.pointer.child_type;
1065
1066 set_debug_source_node(g, node);
1067
1068 size_t wanted_ptr_index = wanted_type->data.structure.fields[0].gen_index;
1069 LLVMValueRef dest_ptr_ptr = LLVMBuildStructGEP(g->builder, cast_expr->tmp_ptr, wanted_ptr_index, "");
1070 LLVMValueRef src_ptr_casted = LLVMBuildBitCast(g->builder, expr_val, wanted_pointer_type->type_ref, "");
1071 LLVMBuildStore(g->builder, src_ptr_casted, dest_ptr_ptr);
1072
1073 size_t wanted_len_index = wanted_type->data.structure.fields[1].gen_index;
1074 LLVMValueRef len_ptr = LLVMBuildStructGEP(g->builder, cast_expr->tmp_ptr, wanted_len_index, "");
1075 LLVMValueRef len_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref,
1076 actual_type->data.array.len / type_size(g, wanted_child_type), false);
1077 LLVMBuildStore(g->builder, len_val, len_ptr);
1078
1079 return cast_expr->tmp_ptr;
1080 }
1081 case CastOpIntToFloat:
1082 assert(actual_type->id == TypeTableEntryIdInt);
1083 if (actual_type->data.integral.is_signed) {
1084 set_debug_source_node(g, node);
1085 return LLVMBuildSIToFP(g->builder, expr_val, wanted_type->type_ref, "");
1086 } else {
1087 set_debug_source_node(g, node);
1088 return LLVMBuildUIToFP(g->builder, expr_val, wanted_type->type_ref, "");
1089 }
1090 case CastOpFloatToInt:
1091 assert(wanted_type->id == TypeTableEntryIdInt);
1092 if (wanted_type->data.integral.is_signed) {
1093 set_debug_source_node(g, node);
1094 return LLVMBuildFPToSI(g->builder, expr_val, wanted_type->type_ref, "");
1095 } else {
1096 set_debug_source_node(g, node);
1097 return LLVMBuildFPToUI(g->builder, expr_val, wanted_type->type_ref, "");
1098 }
1099
1100 case CastOpBoolToInt:
1101 assert(wanted_type->id == TypeTableEntryIdInt);
1102 assert(actual_type->id == TypeTableEntryIdBool);
1103 set_debug_source_node(g, node);
1104 return LLVMBuildZExt(g->builder, expr_val, wanted_type->type_ref, "");
1105
1106 case CastOpIntToEnum:
1107 return gen_widen_or_shorten(g, node, actual_type, wanted_type->data.enumeration.tag_type, expr_val);
1108 case CastOpEnumToInt:
1109 return gen_widen_or_shorten(g, node, actual_type->data.enumeration.tag_type, wanted_type, expr_val);
1110 }
1111 zig_unreachable();
1112}
1113
1114
1115static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) {851static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) {
1116 assert(node->type == NodeTypeFnCallExpr);852 assert(node->type == NodeTypeFnCallExpr);
1117853
1118 if (node->data.fn_call_expr.is_builtin) {854 if (node->data.fn_call_expr.is_builtin) {
1119 return gen_builtin_fn_call_expr(g, node);855 return gen_builtin_fn_call_expr(g, node);
1120 } else if (node->data.fn_call_expr.cast_op != CastOpNoCast) {
1121 return gen_cast_expr(g, node);
1122 }856 }
1123857
1124 FnTableEntry *fn_table_entry = node->data.fn_call_expr.fn_entry;858 FnTableEntry *fn_table_entry = node->data.fn_call_expr.fn_entry;
...@@ -1186,7 +920,6 @@ static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) {...@@ -1186,7 +920,6 @@ static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) {
1186 }920 }
1187 }921 }
1188922
1189 set_debug_source_node(g, node);
1190 LLVMValueRef result = ZigLLVMBuildCall(g->builder, fn_val,923 LLVMValueRef result = ZigLLVMBuildCall(g->builder, fn_val,
1191 gen_param_values, gen_param_index, fn_type->data.fn.calling_convention, "");924 gen_param_values, gen_param_index, fn_type->data.fn.calling_convention, "");
1192925
...@@ -1209,7 +942,6 @@ static LLVMValueRef gen_array_base_ptr(CodeGen *g, AstNode *node) {...@@ -1209,7 +942,6 @@ static LLVMValueRef gen_array_base_ptr(CodeGen *g, AstNode *node) {
1209 array_ptr = gen_field_access_expr(g, node, true);942 array_ptr = gen_field_access_expr(g, node, true);
1210 if (type_entry->id == TypeTableEntryIdPointer) {943 if (type_entry->id == TypeTableEntryIdPointer) {
1211 // we have a double pointer so we must dereference it once944 // we have a double pointer so we must dereference it once
1212 set_debug_source_node(g, node);
1213 array_ptr = LLVMBuildLoad(g->builder, array_ptr, "");945 array_ptr = LLVMBuildLoad(g->builder, array_ptr, "");
1214 }946 }
1215 } else {947 } else {
...@@ -1234,20 +966,18 @@ static LLVMValueRef gen_array_elem_ptr(CodeGen *g, AstNode *source_node, LLVMVal...@@ -1234,20 +966,18 @@ static LLVMValueRef gen_array_elem_ptr(CodeGen *g, AstNode *source_node, LLVMVal
1234 if (want_debug_safety(g, source_node)) {966 if (want_debug_safety(g, source_node)) {
1235 LLVMValueRef end = LLVMConstInt(g->builtin_types.entry_usize->type_ref,967 LLVMValueRef end = LLVMConstInt(g->builtin_types.entry_usize->type_ref,
1236 array_type->data.array.len, false);968 array_type->data.array.len, false);
1237 add_bounds_check(g, source_node, subscript_value, LLVMIntEQ, nullptr, LLVMIntULT, end);969 add_bounds_check(g, subscript_value, LLVMIntEQ, nullptr, LLVMIntULT, end);
1238 }970 }
1239 LLVMValueRef indices[] = {971 LLVMValueRef indices[] = {
1240 LLVMConstNull(g->builtin_types.entry_usize->type_ref),972 LLVMConstNull(g->builtin_types.entry_usize->type_ref),
1241 subscript_value973 subscript_value
1242 };974 };
1243 set_debug_source_node(g, source_node);
1244 return LLVMBuildInBoundsGEP(g->builder, array_ptr, indices, 2, "");975 return LLVMBuildInBoundsGEP(g->builder, array_ptr, indices, 2, "");
1245 } else if (array_type->id == TypeTableEntryIdPointer) {976 } else if (array_type->id == TypeTableEntryIdPointer) {
1246 assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMPointerTypeKind);977 assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMPointerTypeKind);
1247 LLVMValueRef indices[] = {978 LLVMValueRef indices[] = {
1248 subscript_value979 subscript_value
1249 };980 };
1250 set_debug_source_node(g, source_node);
1251 return LLVMBuildInBoundsGEP(g->builder, array_ptr, indices, 1, "");981 return LLVMBuildInBoundsGEP(g->builder, array_ptr, indices, 1, "");
1252 } else if (array_type->id == TypeTableEntryIdStruct) {982 } else if (array_type->id == TypeTableEntryIdStruct) {
1253 assert(array_type->data.structure.is_slice);983 assert(array_type->data.structure.is_slice);
...@@ -1255,15 +985,13 @@ static LLVMValueRef gen_array_elem_ptr(CodeGen *g, AstNode *source_node, LLVMVal...@@ -1255,15 +985,13 @@ static LLVMValueRef gen_array_elem_ptr(CodeGen *g, AstNode *source_node, LLVMVal
1255 assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(array_ptr))) == LLVMStructTypeKind);985 assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(array_ptr))) == LLVMStructTypeKind);
1256986
1257 if (want_debug_safety(g, source_node)) {987 if (want_debug_safety(g, source_node)) {
1258 set_debug_source_node(g, source_node);
1259 size_t len_index = array_type->data.structure.fields[1].gen_index;988 size_t len_index = array_type->data.structure.fields[1].gen_index;
1260 assert(len_index != SIZE_MAX);989 assert(len_index != SIZE_MAX);
1261 LLVMValueRef len_ptr = LLVMBuildStructGEP(g->builder, array_ptr, len_index, "");990 LLVMValueRef len_ptr = LLVMBuildStructGEP(g->builder, array_ptr, len_index, "");
1262 LLVMValueRef len = LLVMBuildLoad(g->builder, len_ptr, "");991 LLVMValueRef len = LLVMBuildLoad(g->builder, len_ptr, "");
1263 add_bounds_check(g, source_node, subscript_value, LLVMIntEQ, nullptr, LLVMIntULT, len);992 add_bounds_check(g, subscript_value, LLVMIntEQ, nullptr, LLVMIntULT, len);
1264 }993 }
1265994
1266 set_debug_source_node(g, source_node);
1267 size_t ptr_index = array_type->data.structure.fields[0].gen_index;995 size_t ptr_index = array_type->data.structure.fields[0].gen_index;
1268 assert(ptr_index != SIZE_MAX);996 assert(ptr_index != SIZE_MAX);
1269 LLVMValueRef ptr_ptr = LLVMBuildStructGEP(g->builder, array_ptr, ptr_index, "");997 LLVMValueRef ptr_ptr = LLVMBuildStructGEP(g->builder, array_ptr, ptr_index, "");
...@@ -1302,7 +1030,6 @@ static LLVMValueRef gen_field_ptr(CodeGen *g, AstNode *node, TypeTableEntry **ou...@@ -1302,7 +1030,6 @@ static LLVMValueRef gen_field_ptr(CodeGen *g, AstNode *node, TypeTableEntry **ou
1302 assert(var);1030 assert(var);
13031031
1304 if (var->type->id == TypeTableEntryIdPointer) {1032 if (var->type->id == TypeTableEntryIdPointer) {
1305 set_debug_source_node(g, node);
1306 struct_ptr = LLVMBuildLoad(g->builder, var->value_ref, "");1033 struct_ptr = LLVMBuildLoad(g->builder, var->value_ref, "");
1307 } else {1034 } else {
1308 struct_ptr = var->value_ref;1035 struct_ptr = var->value_ref;
...@@ -1312,7 +1039,6 @@ static LLVMValueRef gen_field_ptr(CodeGen *g, AstNode *node, TypeTableEntry **ou...@@ -1312,7 +1039,6 @@ static LLVMValueRef gen_field_ptr(CodeGen *g, AstNode *node, TypeTableEntry **ou
1312 TypeTableEntry *field_type = get_expr_type(struct_expr_node);1039 TypeTableEntry *field_type = get_expr_type(struct_expr_node);
1313 if (field_type->id == TypeTableEntryIdPointer) {1040 if (field_type->id == TypeTableEntryIdPointer) {
1314 // we have a double pointer so we must dereference it once1041 // we have a double pointer so we must dereference it once
1315 set_debug_source_node(g, node);
1316 struct_ptr = LLVMBuildLoad(g->builder, struct_ptr, "");1042 struct_ptr = LLVMBuildLoad(g->builder, struct_ptr, "");
1317 }1043 }
1318 } else {1044 } else {
...@@ -1325,7 +1051,6 @@ static LLVMValueRef gen_field_ptr(CodeGen *g, AstNode *node, TypeTableEntry **ou...@@ -1325,7 +1051,6 @@ static LLVMValueRef gen_field_ptr(CodeGen *g, AstNode *node, TypeTableEntry **ou
1325 size_t gen_field_index = node->data.field_access_expr.type_struct_field->gen_index;1051 size_t gen_field_index = node->data.field_access_expr.type_struct_field->gen_index;
1326 assert(gen_field_index != SIZE_MAX);1052 assert(gen_field_index != SIZE_MAX);
13271053
1328 set_debug_source_node(g, node);
1329 return LLVMBuildStructGEP(g->builder, struct_ptr, gen_field_index, "");1054 return LLVMBuildStructGEP(g->builder, struct_ptr, gen_field_index, "");
1330}1055}
13311056
...@@ -1348,15 +1073,14 @@ static LLVMValueRef gen_slice_expr(CodeGen *g, AstNode *node) {...@@ -1348,15 +1073,14 @@ static LLVMValueRef gen_slice_expr(CodeGen *g, AstNode *node) {
1348 }1073 }
13491074
1350 if (want_debug_safety(g, node)) {1075 if (want_debug_safety(g, node)) {
1351 add_bounds_check(g, node, start_val, LLVMIntEQ, nullptr, LLVMIntULE, end_val);1076 add_bounds_check(g, start_val, LLVMIntEQ, nullptr, LLVMIntULE, end_val);
1352 if (node->data.slice_expr.end) {1077 if (node->data.slice_expr.end) {
1353 LLVMValueRef array_end = LLVMConstInt(g->builtin_types.entry_usize->type_ref,1078 LLVMValueRef array_end = LLVMConstInt(g->builtin_types.entry_usize->type_ref,
1354 array_type->data.array.len, false);1079 array_type->data.array.len, false);
1355 add_bounds_check(g, node, end_val, LLVMIntEQ, nullptr, LLVMIntULE, array_end);1080 add_bounds_check(g, end_val, LLVMIntEQ, nullptr, LLVMIntULE, array_end);
1356 }1081 }
1357 }1082 }
13581083
1359 set_debug_source_node(g, node);
1360 LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, 0, "");1084 LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, 0, "");
1361 LLVMValueRef indices[] = {1085 LLVMValueRef indices[] = {
1362 LLVMConstNull(g->builtin_types.entry_usize->type_ref),1086 LLVMConstNull(g->builtin_types.entry_usize->type_ref),
...@@ -1375,10 +1099,9 @@ static LLVMValueRef gen_slice_expr(CodeGen *g, AstNode *node) {...@@ -1375,10 +1099,9 @@ static LLVMValueRef gen_slice_expr(CodeGen *g, AstNode *node) {
1375 LLVMValueRef end_val = gen_expr(g, node->data.slice_expr.end);1099 LLVMValueRef end_val = gen_expr(g, node->data.slice_expr.end);
13761100
1377 if (want_debug_safety(g, node)) {1101 if (want_debug_safety(g, node)) {
1378 add_bounds_check(g, node, start_val, LLVMIntEQ, nullptr, LLVMIntULE, end_val);1102 add_bounds_check(g, start_val, LLVMIntEQ, nullptr, LLVMIntULE, end_val);
1379 }1103 }
13801104
1381 set_debug_source_node(g, node);
1382 LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, 0, "");1105 LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, 0, "");
1383 LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, array_ptr, &start_val, 1, "");1106 LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, array_ptr, &start_val, 1, "");
1384 LLVMBuildStore(g->builder, slice_start_ptr, ptr_field_ptr);1107 LLVMBuildStore(g->builder, slice_start_ptr, ptr_field_ptr);
...@@ -1400,7 +1123,6 @@ static LLVMValueRef gen_slice_expr(CodeGen *g, AstNode *node) {...@@ -1400,7 +1123,6 @@ static LLVMValueRef gen_slice_expr(CodeGen *g, AstNode *node) {
14001123
1401 LLVMValueRef prev_end = nullptr;1124 LLVMValueRef prev_end = nullptr;
1402 if (!node->data.slice_expr.end || want_debug_safety(g, node)) {1125 if (!node->data.slice_expr.end || want_debug_safety(g, node)) {
1403 set_debug_source_node(g, node);
1404 LLVMValueRef src_len_ptr = LLVMBuildStructGEP(g->builder, array_ptr, len_index, "");1126 LLVMValueRef src_len_ptr = LLVMBuildStructGEP(g->builder, array_ptr, len_index, "");
1405 prev_end = LLVMBuildLoad(g->builder, src_len_ptr, "");1127 prev_end = LLVMBuildLoad(g->builder, src_len_ptr, "");
1406 }1128 }
...@@ -1415,13 +1137,12 @@ static LLVMValueRef gen_slice_expr(CodeGen *g, AstNode *node) {...@@ -1415,13 +1137,12 @@ static LLVMValueRef gen_slice_expr(CodeGen *g, AstNode *node) {
14151137
1416 if (want_debug_safety(g, node)) {1138 if (want_debug_safety(g, node)) {
1417 assert(prev_end);1139 assert(prev_end);
1418 add_bounds_check(g, node, start_val, LLVMIntEQ, nullptr, LLVMIntULE, end_val);1140 add_bounds_check(g, start_val, LLVMIntEQ, nullptr, LLVMIntULE, end_val);
1419 if (node->data.slice_expr.end) {1141 if (node->data.slice_expr.end) {
1420 add_bounds_check(g, node, end_val, LLVMIntEQ, nullptr, LLVMIntULE, prev_end);1142 add_bounds_check(g, end_val, LLVMIntEQ, nullptr, LLVMIntULE, prev_end);
1421 }1143 }
1422 }1144 }
14231145
1424 set_debug_source_node(g, node);
1425 LLVMValueRef src_ptr_ptr = LLVMBuildStructGEP(g->builder, array_ptr, ptr_index, "");1146 LLVMValueRef src_ptr_ptr = LLVMBuildStructGEP(g->builder, array_ptr, ptr_index, "");
1426 LLVMValueRef src_ptr = LLVMBuildLoad(g->builder, src_ptr_ptr, "");1147 LLVMValueRef src_ptr = LLVMBuildLoad(g->builder, src_ptr_ptr, "");
1427 LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, ptr_index, "");1148 LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, ptr_index, "");
...@@ -1461,7 +1182,6 @@ static LLVMValueRef gen_array_access_expr(CodeGen *g, AstNode *node, bool is_lva...@@ -1461,7 +1182,6 @@ static LLVMValueRef gen_array_access_expr(CodeGen *g, AstNode *node, bool is_lva
1461 if (is_lvalue || !ptr || handle_is_ptr(child_type)) {1182 if (is_lvalue || !ptr || handle_is_ptr(child_type)) {
1462 return ptr;1183 return ptr;
1463 } else {1184 } else {
1464 set_debug_source_node(g, node);
1465 return LLVMBuildLoad(g->builder, ptr, "");1185 return LLVMBuildLoad(g->builder, ptr, "");
1466 }1186 }
1467}1187}
...@@ -1471,7 +1191,7 @@ static LLVMValueRef gen_variable(CodeGen *g, AstNode *source_node, VariableTable...@@ -1471,7 +1191,7 @@ static LLVMValueRef gen_variable(CodeGen *g, AstNode *source_node, VariableTable
1471 return nullptr;1191 return nullptr;
1472 } else {1192 } else {
1473 assert(variable->value_ref);1193 assert(variable->value_ref);
1474 return get_handle_value(g, source_node, variable->value_ref, variable->type);1194 return get_handle_value(g, variable->value_ref, variable->type);
1475 }1195 }
1476}1196}
14771197
...@@ -1494,7 +1214,6 @@ static LLVMValueRef gen_field_access_expr(CodeGen *g, AstNode *node, bool is_lva...@@ -1494,7 +1214,6 @@ static LLVMValueRef gen_field_access_expr(CodeGen *g, AstNode *node, bool is_lva
1494 if (is_lvalue || handle_is_ptr(type_entry)) {1214 if (is_lvalue || handle_is_ptr(type_entry)) {
1495 return ptr;1215 return ptr;
1496 } else {1216 } else {
1497 set_debug_source_node(g, node);
1498 return LLVMBuildLoad(g->builder, ptr, "");1217 return LLVMBuildLoad(g->builder, ptr, "");
1499 }1218 }
1500 } else if (struct_type->id == TypeTableEntryIdMetaType) {1219 } else if (struct_type->id == TypeTableEntryIdMetaType) {
...@@ -1631,7 +1350,6 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) {...@@ -1631,7 +1350,6 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) {
1631 case PrefixOpNegationWrap:1350 case PrefixOpNegationWrap:
1632 {1351 {
1633 LLVMValueRef expr = gen_expr(g, expr_node);1352 LLVMValueRef expr = gen_expr(g, expr_node);
1634 set_debug_source_node(g, node);
1635 if (expr_type->id == TypeTableEntryIdFloat) {1353 if (expr_type->id == TypeTableEntryIdFloat) {
1636 return LLVMBuildFNeg(g->builder, expr, "");1354 return LLVMBuildFNeg(g->builder, expr, "");
1637 } else if (expr_type->id == TypeTableEntryIdInt) {1355 } else if (expr_type->id == TypeTableEntryIdInt) {
...@@ -1653,13 +1371,11 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) {...@@ -1653,13 +1371,11 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) {
1653 {1371 {
1654 LLVMValueRef expr = gen_expr(g, expr_node);1372 LLVMValueRef expr = gen_expr(g, expr_node);
1655 LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(expr));1373 LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(expr));
1656 set_debug_source_node(g, node);
1657 return LLVMBuildICmp(g->builder, LLVMIntEQ, expr, zero, "");1374 return LLVMBuildICmp(g->builder, LLVMIntEQ, expr, zero, "");
1658 }1375 }
1659 case PrefixOpBinNot:1376 case PrefixOpBinNot:
1660 {1377 {
1661 LLVMValueRef expr = gen_expr(g, expr_node);1378 LLVMValueRef expr = gen_expr(g, expr_node);
1662 set_debug_source_node(g, node);
1663 return LLVMBuildNot(g->builder, expr, "");1379 return LLVMBuildNot(g->builder, expr, "");
1664 }1380 }
1665 case PrefixOpAddressOf:1381 case PrefixOpAddressOf:
...@@ -1677,7 +1393,7 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) {...@@ -1677,7 +1393,7 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) {
1677 return nullptr;1393 return nullptr;
1678 } else {1394 } else {
1679 TypeTableEntry *child_type = expr_type->data.pointer.child_type;1395 TypeTableEntry *child_type = expr_type->data.pointer.child_type;
1680 return get_handle_value(g, node, expr, child_type);1396 return get_handle_value(g, expr, child_type);
1681 }1397 }
1682 }1398 }
1683 case PrefixOpMaybe:1399 case PrefixOpMaybe:
...@@ -1698,13 +1414,11 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) {...@@ -1698,13 +1414,11 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) {
1698 if (want_debug_safety(g, node)) {1414 if (want_debug_safety(g, node)) {
1699 LLVMValueRef err_val;1415 LLVMValueRef err_val;
1700 if (type_has_bits(child_type)) {1416 if (type_has_bits(child_type)) {
1701 set_debug_source_node(g, node);
1702 LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, expr_val, 0, "");1417 LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, expr_val, 0, "");
1703 err_val = LLVMBuildLoad(g->builder, err_val_ptr, "");1418 err_val = LLVMBuildLoad(g->builder, err_val_ptr, "");
1704 } else {1419 } else {
1705 err_val = expr_val;1420 err_val = expr_val;
1706 }1421 }
1707 set_debug_source_node(g, node);
1708 LLVMValueRef zero = LLVMConstNull(g->err_tag_type->type_ref);1422 LLVMValueRef zero = LLVMConstNull(g->err_tag_type->type_ref);
1709 LLVMValueRef cond_val = LLVMBuildICmp(g->builder, LLVMIntEQ, err_val, zero, "");1423 LLVMValueRef cond_val = LLVMBuildICmp(g->builder, LLVMIntEQ, err_val, zero, "");
1710 LLVMBasicBlockRef err_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "UnwrapErrError");1424 LLVMBasicBlockRef err_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "UnwrapErrError");
...@@ -1719,7 +1433,7 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) {...@@ -1719,7 +1433,7 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) {
17191433
1720 if (type_has_bits(child_type)) {1434 if (type_has_bits(child_type)) {
1721 LLVMValueRef child_val_ptr = LLVMBuildStructGEP(g->builder, expr_val, 1, "");1435 LLVMValueRef child_val_ptr = LLVMBuildStructGEP(g->builder, expr_val, 1, "");
1722 return get_handle_value(g, expr_node, child_val_ptr, child_type);1436 return get_handle_value(g, child_val_ptr, child_type);
1723 } else {1437 } else {
1724 return nullptr;1438 return nullptr;
1725 }1439 }
...@@ -1733,7 +1447,6 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) {...@@ -1733,7 +1447,6 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) {
1733 TypeTableEntry *child_type = expr_type->data.maybe.child_type;1447 TypeTableEntry *child_type = expr_type->data.maybe.child_type;
17341448
1735 if (want_debug_safety(g, node)) {1449 if (want_debug_safety(g, node)) {
1736 set_debug_source_node(g, node);
1737 LLVMValueRef cond_val;1450 LLVMValueRef cond_val;
1738 if (child_type->id == TypeTableEntryIdPointer ||1451 if (child_type->id == TypeTableEntryIdPointer ||
1739 child_type->id == TypeTableEntryIdFn)1452 child_type->id == TypeTableEntryIdFn)
...@@ -1761,9 +1474,8 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) {...@@ -1761,9 +1474,8 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) {
1761 {1474 {
1762 return expr_val;1475 return expr_val;
1763 } else {1476 } else {
1764 set_debug_source_node(g, node);
1765 LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP(g->builder, expr_val, 0, "");1477 LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP(g->builder, expr_val, 0, "");
1766 return get_handle_value(g, node, maybe_field_ptr, child_type);1478 return get_handle_value(g, maybe_field_ptr, child_type);
1767 }1479 }
1768 }1480 }
1769 }1481 }
...@@ -1773,7 +1485,6 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) {...@@ -1773,7 +1485,6 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) {
1773static LLVMValueRef gen_div(CodeGen *g, AstNode *source_node, LLVMValueRef val1, LLVMValueRef val2,1485static LLVMValueRef gen_div(CodeGen *g, AstNode *source_node, LLVMValueRef val1, LLVMValueRef val2,
1774 TypeTableEntry *type_entry, bool exact)1486 TypeTableEntry *type_entry, bool exact)
1775{1487{
1776 set_debug_source_node(g, source_node);
17771488
1778 if (want_debug_safety(g, source_node)) {1489 if (want_debug_safety(g, source_node)) {
1779 LLVMValueRef zero = LLVMConstNull(type_entry->type_ref);1490 LLVMValueRef zero = LLVMConstNull(type_entry->type_ref);
...@@ -1846,22 +1557,18 @@ static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, AstNode *source_node,...@@ -1846,22 +1557,18 @@ static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, AstNode *source_node,
1846 switch (bin_op) {1557 switch (bin_op) {
1847 case BinOpTypeBinOr:1558 case BinOpTypeBinOr:
1848 case BinOpTypeAssignBitOr:1559 case BinOpTypeAssignBitOr:
1849 set_debug_source_node(g, source_node);
1850 return LLVMBuildOr(g->builder, val1, val2, "");1560 return LLVMBuildOr(g->builder, val1, val2, "");
1851 case BinOpTypeBinXor:1561 case BinOpTypeBinXor:
1852 case BinOpTypeAssignBitXor:1562 case BinOpTypeAssignBitXor:
1853 set_debug_source_node(g, source_node);
1854 return LLVMBuildXor(g->builder, val1, val2, "");1563 return LLVMBuildXor(g->builder, val1, val2, "");
1855 case BinOpTypeBinAnd:1564 case BinOpTypeBinAnd:
1856 case BinOpTypeAssignBitAnd:1565 case BinOpTypeAssignBitAnd:
1857 set_debug_source_node(g, source_node);
1858 return LLVMBuildAnd(g->builder, val1, val2, "");1566 return LLVMBuildAnd(g->builder, val1, val2, "");
1859 case BinOpTypeBitShiftLeft:1567 case BinOpTypeBitShiftLeft:
1860 case BinOpTypeBitShiftLeftWrap:1568 case BinOpTypeBitShiftLeftWrap:
1861 case BinOpTypeAssignBitShiftLeft:1569 case BinOpTypeAssignBitShiftLeft:
1862 case BinOpTypeAssignBitShiftLeftWrap:1570 case BinOpTypeAssignBitShiftLeftWrap:
1863 {1571 {
1864 set_debug_source_node(g, source_node);
1865 assert(op1_type->id == TypeTableEntryIdInt);1572 assert(op1_type->id == TypeTableEntryIdInt);
1866 bool is_wrapping = (bin_op == BinOpTypeBitShiftLeftWrap) ||1573 bool is_wrapping = (bin_op == BinOpTypeBitShiftLeftWrap) ||
1867 (bin_op == BinOpTypeAssignBitShiftLeftWrap);1574 (bin_op == BinOpTypeAssignBitShiftLeftWrap);
...@@ -1880,7 +1587,6 @@ static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, AstNode *source_node,...@@ -1880,7 +1587,6 @@ static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, AstNode *source_node,
1880 assert(op1_type->id == TypeTableEntryIdInt);1587 assert(op1_type->id == TypeTableEntryIdInt);
1881 assert(op2_type->id == TypeTableEntryIdInt);1588 assert(op2_type->id == TypeTableEntryIdInt);
18821589
1883 set_debug_source_node(g, source_node);
1884 if (op1_type->data.integral.is_signed) {1590 if (op1_type->data.integral.is_signed) {
1885 return LLVMBuildAShr(g->builder, val1, val2, "");1591 return LLVMBuildAShr(g->builder, val1, val2, "");
1886 } else {1592 } else {
...@@ -1890,7 +1596,6 @@ static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, AstNode *source_node,...@@ -1890,7 +1596,6 @@ static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, AstNode *source_node,
1890 case BinOpTypeAddWrap:1596 case BinOpTypeAddWrap:
1891 case BinOpTypeAssignPlus:1597 case BinOpTypeAssignPlus:
1892 case BinOpTypeAssignPlusWrap:1598 case BinOpTypeAssignPlusWrap:
1893 set_debug_source_node(g, source_node);
1894 if (op1_type->id == TypeTableEntryIdFloat) {1599 if (op1_type->id == TypeTableEntryIdFloat) {
1895 return LLVMBuildFAdd(g->builder, val1, val2, "");1600 return LLVMBuildFAdd(g->builder, val1, val2, "");
1896 } else if (op1_type->id == TypeTableEntryIdInt) {1601 } else if (op1_type->id == TypeTableEntryIdInt) {
...@@ -1911,7 +1616,6 @@ static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, AstNode *source_node,...@@ -1911,7 +1616,6 @@ static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, AstNode *source_node,
1911 case BinOpTypeSubWrap:1616 case BinOpTypeSubWrap:
1912 case BinOpTypeAssignMinus:1617 case BinOpTypeAssignMinus:
1913 case BinOpTypeAssignMinusWrap:1618 case BinOpTypeAssignMinusWrap:
1914 set_debug_source_node(g, source_node);
1915 if (op1_type->id == TypeTableEntryIdFloat) {1619 if (op1_type->id == TypeTableEntryIdFloat) {
1916 return LLVMBuildFSub(g->builder, val1, val2, "");1620 return LLVMBuildFSub(g->builder, val1, val2, "");
1917 } else if (op1_type->id == TypeTableEntryIdInt) {1621 } else if (op1_type->id == TypeTableEntryIdInt) {
...@@ -1932,7 +1636,6 @@ static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, AstNode *source_node,...@@ -1932,7 +1636,6 @@ static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, AstNode *source_node,
1932 case BinOpTypeMultWrap:1636 case BinOpTypeMultWrap:
1933 case BinOpTypeAssignTimes:1637 case BinOpTypeAssignTimes:
1934 case BinOpTypeAssignTimesWrap:1638 case BinOpTypeAssignTimesWrap:
1935 set_debug_source_node(g, source_node);
1936 if (op1_type->id == TypeTableEntryIdFloat) {1639 if (op1_type->id == TypeTableEntryIdFloat) {
1937 return LLVMBuildFMul(g->builder, val1, val2, "");1640 return LLVMBuildFMul(g->builder, val1, val2, "");
1938 } else if (op1_type->id == TypeTableEntryIdInt) {1641 } else if (op1_type->id == TypeTableEntryIdInt) {
...@@ -1954,7 +1657,6 @@ static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, AstNode *source_node,...@@ -1954,7 +1657,6 @@ static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, AstNode *source_node,
1954 return gen_div(g, source_node, val1, val2, op1_type, false);1657 return gen_div(g, source_node, val1, val2, op1_type, false);
1955 case BinOpTypeMod:1658 case BinOpTypeMod:
1956 case BinOpTypeAssignMod:1659 case BinOpTypeAssignMod:
1957 set_debug_source_node(g, source_node);
1958 if (op1_type->id == TypeTableEntryIdFloat) {1660 if (op1_type->id == TypeTableEntryIdFloat) {
1959 return LLVMBuildFRem(g->builder, val1, val2, "");1661 return LLVMBuildFRem(g->builder, val1, val2, "");
1960 } else {1662 } else {
...@@ -2044,7 +1746,6 @@ static LLVMValueRef gen_cmp_expr(CodeGen *g, AstNode *node) {...@@ -2044,7 +1746,6 @@ static LLVMValueRef gen_cmp_expr(CodeGen *g, AstNode *node) {
2044 TypeTableEntry *op2_type = get_expr_type(node->data.bin_op_expr.op2);1746 TypeTableEntry *op2_type = get_expr_type(node->data.bin_op_expr.op2);
2045 assert(op1_type == op2_type);1747 assert(op1_type == op2_type);
20461748
2047 set_debug_source_node(g, node);
2048 if (op1_type->id == TypeTableEntryIdFloat) {1749 if (op1_type->id == TypeTableEntryIdFloat) {
2049 LLVMRealPredicate pred = cmp_op_to_real_predicate(node->data.bin_op_expr.bin_op);1750 LLVMRealPredicate pred = cmp_op_to_real_predicate(node->data.bin_op_expr.bin_op);
2050 return LLVMBuildFCmp(g->builder, pred, val1, val2, "");1751 return LLVMBuildFCmp(g->builder, pred, val1, val2, "");
...@@ -2081,18 +1782,15 @@ static LLVMValueRef gen_bool_and_expr(CodeGen *g, AstNode *node) {...@@ -2081,18 +1782,15 @@ static LLVMValueRef gen_bool_and_expr(CodeGen *g, AstNode *node) {
2081 // block for when val1 == false (don't even evaluate the second part)1782 // block for when val1 == false (don't even evaluate the second part)
2082 LLVMBasicBlockRef false_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "BoolAndFalse");1783 LLVMBasicBlockRef false_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "BoolAndFalse");
20831784
2084 set_debug_source_node(g, node);
2085 LLVMBuildCondBr(g->builder, val1, true_block, false_block);1785 LLVMBuildCondBr(g->builder, val1, true_block, false_block);
20861786
2087 LLVMPositionBuilderAtEnd(g->builder, true_block);1787 LLVMPositionBuilderAtEnd(g->builder, true_block);
2088 LLVMValueRef val2 = gen_expr(g, node->data.bin_op_expr.op2);1788 LLVMValueRef val2 = gen_expr(g, node->data.bin_op_expr.op2);
2089 LLVMBasicBlockRef post_val2_block = LLVMGetInsertBlock(g->builder);1789 LLVMBasicBlockRef post_val2_block = LLVMGetInsertBlock(g->builder);
20901790
2091 set_debug_source_node(g, node);
2092 LLVMBuildBr(g->builder, false_block);1791 LLVMBuildBr(g->builder, false_block);
20931792
2094 LLVMPositionBuilderAtEnd(g->builder, false_block);1793 LLVMPositionBuilderAtEnd(g->builder, false_block);
2095 set_debug_source_node(g, node);
2096 LLVMValueRef phi = LLVMBuildPhi(g->builder, LLVMInt1Type(), "");1794 LLVMValueRef phi = LLVMBuildPhi(g->builder, LLVMInt1Type(), "");
2097 LLVMValueRef incoming_values[2] = {val1, val2};1795 LLVMValueRef incoming_values[2] = {val1, val2};
2098 LLVMBasicBlockRef incoming_blocks[2] = {post_val1_block, post_val2_block};1796 LLVMBasicBlockRef incoming_blocks[2] = {post_val1_block, post_val2_block};
...@@ -2112,7 +1810,6 @@ static LLVMValueRef gen_bool_or_expr(CodeGen *g, AstNode *expr_node) {...@@ -2112,7 +1810,6 @@ static LLVMValueRef gen_bool_or_expr(CodeGen *g, AstNode *expr_node) {
2112 // block for when val1 == true (don't even evaluate the second part)1810 // block for when val1 == true (don't even evaluate the second part)
2113 LLVMBasicBlockRef true_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "BoolOrTrue");1811 LLVMBasicBlockRef true_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "BoolOrTrue");
21141812
2115 set_debug_source_node(g, expr_node);
2116 LLVMBuildCondBr(g->builder, val1, true_block, false_block);1813 LLVMBuildCondBr(g->builder, val1, true_block, false_block);
21171814
2118 LLVMPositionBuilderAtEnd(g->builder, false_block);1815 LLVMPositionBuilderAtEnd(g->builder, false_block);
...@@ -2120,11 +1817,9 @@ static LLVMValueRef gen_bool_or_expr(CodeGen *g, AstNode *expr_node) {...@@ -2120,11 +1817,9 @@ static LLVMValueRef gen_bool_or_expr(CodeGen *g, AstNode *expr_node) {
21201817
2121 LLVMBasicBlockRef post_val2_block = LLVMGetInsertBlock(g->builder);1818 LLVMBasicBlockRef post_val2_block = LLVMGetInsertBlock(g->builder);
21221819
2123 set_debug_source_node(g, expr_node);
2124 LLVMBuildBr(g->builder, true_block);1820 LLVMBuildBr(g->builder, true_block);
21251821
2126 LLVMPositionBuilderAtEnd(g->builder, true_block);1822 LLVMPositionBuilderAtEnd(g->builder, true_block);
2127 set_debug_source_node(g, expr_node);
2128 LLVMValueRef phi = LLVMBuildPhi(g->builder, LLVMInt1Type(), "");1823 LLVMValueRef phi = LLVMBuildPhi(g->builder, LLVMInt1Type(), "");
2129 LLVMValueRef incoming_values[2] = {val1, val2};1824 LLVMValueRef incoming_values[2] = {val1, val2};
2130 LLVMBasicBlockRef incoming_blocks[2] = {post_val1_block, post_val2_block};1825 LLVMBasicBlockRef incoming_blocks[2] = {post_val1_block, post_val2_block};
...@@ -2133,14 +1828,13 @@ static LLVMValueRef gen_bool_or_expr(CodeGen *g, AstNode *expr_node) {...@@ -2133,14 +1828,13 @@ static LLVMValueRef gen_bool_or_expr(CodeGen *g, AstNode *expr_node) {
2133 return phi;1828 return phi;
2134}1829}
21351830
2136static LLVMValueRef gen_struct_memcpy(CodeGen *g, AstNode *source_node, LLVMValueRef src, LLVMValueRef dest,1831static LLVMValueRef gen_struct_memcpy(CodeGen *g, LLVMValueRef src, LLVMValueRef dest,
2137 TypeTableEntry *type_entry)1832 TypeTableEntry *type_entry)
2138{1833{
2139 assert(handle_is_ptr(type_entry));1834 assert(handle_is_ptr(type_entry));
21401835
2141 LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);1836 LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
21421837
2143 set_debug_source_node(g, source_node);
2144 LLVMValueRef src_ptr = LLVMBuildBitCast(g->builder, src, ptr_u8, "");1838 LLVMValueRef src_ptr = LLVMBuildBitCast(g->builder, src, ptr_u8, "");
2145 LLVMValueRef dest_ptr = LLVMBuildBitCast(g->builder, dest, ptr_u8, "");1839 LLVMValueRef dest_ptr = LLVMBuildBitCast(g->builder, dest, ptr_u8, "");
21461840
...@@ -2172,18 +1866,16 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, AstNode *source_node, BinOpType b...@@ -2172,18 +1866,16 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, AstNode *source_node, BinOpType b
2172 assert(op1_type == op2_type);1866 assert(op1_type == op2_type);
2173 assert(bin_op == BinOpTypeAssign);1867 assert(bin_op == BinOpTypeAssign);
21741868
2175 return gen_struct_memcpy(g, source_node, value, target_ref, op1_type);1869 return gen_struct_memcpy(g, value, target_ref, op1_type);
2176 }1870 }
21771871
2178 if (bin_op != BinOpTypeAssign) {1872 if (bin_op != BinOpTypeAssign) {
2179 assert(source_node->type == NodeTypeBinOpExpr);1873 assert(source_node->type == NodeTypeBinOpExpr);
2180 set_debug_source_node(g, source_node->data.bin_op_expr.op1);
2181 LLVMValueRef left_value = LLVMBuildLoad(g->builder, target_ref, "");1874 LLVMValueRef left_value = LLVMBuildLoad(g->builder, target_ref, "");
21821875
2183 value = gen_arithmetic_bin_op(g, source_node, left_value, value, op1_type, op2_type, bin_op);1876 value = gen_arithmetic_bin_op(g, source_node, left_value, value, op1_type, op2_type, bin_op);
2184 }1877 }
21851878
2186 set_debug_source_node(g, source_node);
2187 LLVMBuildStore(g->builder, value, target_ref);1879 LLVMBuildStore(g->builder, value, target_ref);
2188 return nullptr;1880 return nullptr;
2189}1881}
...@@ -2214,9 +1906,8 @@ static LLVMValueRef gen_unwrap_maybe(CodeGen *g, AstNode *node, LLVMValueRef may...@@ -2214,9 +1906,8 @@ static LLVMValueRef gen_unwrap_maybe(CodeGen *g, AstNode *node, LLVMValueRef may
2214 {1906 {
2215 return maybe_struct_ref;1907 return maybe_struct_ref;
2216 } else {1908 } else {
2217 set_debug_source_node(g, node);
2218 LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP(g->builder, maybe_struct_ref, 0, "");1909 LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP(g->builder, maybe_struct_ref, 0, "");
2219 return get_handle_value(g, node, maybe_field_ptr, child_type);1910 return get_handle_value(g, maybe_field_ptr, child_type);
2220 }1911 }
2221}1912}
22221913
...@@ -2240,7 +1931,6 @@ static LLVMValueRef gen_unwrap_maybe_expr(CodeGen *g, AstNode *node) {...@@ -2240,7 +1931,6 @@ static LLVMValueRef gen_unwrap_maybe_expr(CodeGen *g, AstNode *node) {
2240 cond_value = LLVMBuildICmp(g->builder, LLVMIntNE, maybe_struct_ref,1931 cond_value = LLVMBuildICmp(g->builder, LLVMIntNE, maybe_struct_ref,
2241 LLVMConstNull(child_type->type_ref), "");1932 LLVMConstNull(child_type->type_ref), "");
2242 } else {1933 } else {
2243 set_debug_source_node(g, node);
2244 LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP(g->builder, maybe_struct_ref, 1, "");1934 LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP(g->builder, maybe_struct_ref, 1, "");
2245 cond_value = LLVMBuildLoad(g->builder, maybe_field_ptr, "");1935 cond_value = LLVMBuildLoad(g->builder, maybe_field_ptr, "");
2246 }1936 }
...@@ -2255,21 +1945,18 @@ static LLVMValueRef gen_unwrap_maybe_expr(CodeGen *g, AstNode *node) {...@@ -2255,21 +1945,18 @@ static LLVMValueRef gen_unwrap_maybe_expr(CodeGen *g, AstNode *node) {
22551945
2256 LLVMPositionBuilderAtEnd(g->builder, non_null_block);1946 LLVMPositionBuilderAtEnd(g->builder, non_null_block);
2257 LLVMValueRef non_null_result = gen_unwrap_maybe(g, op1_node, maybe_struct_ref);1947 LLVMValueRef non_null_result = gen_unwrap_maybe(g, op1_node, maybe_struct_ref);
2258 set_debug_source_node(g, node);
2259 LLVMBuildBr(g->builder, end_block);1948 LLVMBuildBr(g->builder, end_block);
2260 LLVMBasicBlockRef post_non_null_result_block = LLVMGetInsertBlock(g->builder);1949 LLVMBasicBlockRef post_non_null_result_block = LLVMGetInsertBlock(g->builder);
22611950
2262 LLVMPositionBuilderAtEnd(g->builder, null_block);1951 LLVMPositionBuilderAtEnd(g->builder, null_block);
2263 LLVMValueRef null_result = gen_expr(g, op2_node);1952 LLVMValueRef null_result = gen_expr(g, op2_node);
2264 if (null_reachable) {1953 if (null_reachable) {
2265 set_debug_source_node(g, node);
2266 LLVMBuildBr(g->builder, end_block);1954 LLVMBuildBr(g->builder, end_block);
2267 }1955 }
2268 LLVMBasicBlockRef post_null_result_block = LLVMGetInsertBlock(g->builder);1956 LLVMBasicBlockRef post_null_result_block = LLVMGetInsertBlock(g->builder);
22691957
2270 LLVMPositionBuilderAtEnd(g->builder, end_block);1958 LLVMPositionBuilderAtEnd(g->builder, end_block);
2271 if (null_reachable) {1959 if (null_reachable) {
2272 set_debug_source_node(g, node);
2273 LLVMValueRef phi = LLVMBuildPhi(g->builder, LLVMTypeOf(non_null_result), "");1960 LLVMValueRef phi = LLVMBuildPhi(g->builder, LLVMTypeOf(non_null_result), "");
2274 LLVMValueRef incoming_values[2] = {non_null_result, null_result};1961 LLVMValueRef incoming_values[2] = {non_null_result, null_result};
2275 LLVMBasicBlockRef incoming_blocks[2] = {post_non_null_result_block, post_null_result_block};1962 LLVMBasicBlockRef incoming_blocks[2] = {post_non_null_result_block, post_null_result_block};
...@@ -2351,7 +2038,6 @@ static LLVMValueRef gen_unwrap_err_expr(CodeGen *g, AstNode *node) {...@@ -2351,7 +2038,6 @@ static LLVMValueRef gen_unwrap_err_expr(CodeGen *g, AstNode *node) {
2351 assert(expr_type->id == TypeTableEntryIdErrorUnion);2038 assert(expr_type->id == TypeTableEntryIdErrorUnion);
2352 TypeTableEntry *child_type = expr_type->data.error.child_type;2039 TypeTableEntry *child_type = expr_type->data.error.child_type;
2353 LLVMValueRef err_val;2040 LLVMValueRef err_val;
2354 set_debug_source_node(g, node);
2355 if (handle_is_ptr(expr_type)) {2041 if (handle_is_ptr(expr_type)) {
2356 LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, expr_val, 0, "");2042 LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, expr_val, 0, "");
2357 err_val = LLVMBuildLoad(g->builder, err_val_ptr, "");2043 err_val = LLVMBuildLoad(g->builder, err_val_ptr, "");
...@@ -2377,7 +2063,6 @@ static LLVMValueRef gen_unwrap_err_expr(CodeGen *g, AstNode *node) {...@@ -2377,7 +2063,6 @@ static LLVMValueRef gen_unwrap_err_expr(CodeGen *g, AstNode *node) {
2377 LLVMBuildStore(g->builder, err_val, var->value_ref);2063 LLVMBuildStore(g->builder, err_val, var->value_ref);
2378 }2064 }
2379 LLVMValueRef err_result = gen_expr(g, op2);2065 LLVMValueRef err_result = gen_expr(g, op2);
2380 set_debug_source_node(g, node);
2381 if (have_end_block) {2066 if (have_end_block) {
2382 LLVMBuildBr(g->builder, end_block);2067 LLVMBuildBr(g->builder, end_block);
2383 } else if (err_reachable) {2068 } else if (err_reachable) {
...@@ -2389,7 +2074,7 @@ static LLVMValueRef gen_unwrap_err_expr(CodeGen *g, AstNode *node) {...@@ -2389,7 +2074,7 @@ static LLVMValueRef gen_unwrap_err_expr(CodeGen *g, AstNode *node) {
2389 return nullptr;2074 return nullptr;
2390 }2075 }
2391 LLVMValueRef child_val_ptr = LLVMBuildStructGEP(g->builder, expr_val, 1, "");2076 LLVMValueRef child_val_ptr = LLVMBuildStructGEP(g->builder, expr_val, 1, "");
2392 LLVMValueRef child_val = get_handle_value(g, node, child_val_ptr, child_type);2077 LLVMValueRef child_val = get_handle_value(g, child_val_ptr, child_type);
23932078
2394 if (!have_end_block) {2079 if (!have_end_block) {
2395 return child_val;2080 return child_val;
...@@ -2452,17 +2137,14 @@ static LLVMValueRef gen_return(CodeGen *g, AstNode *source_node, LLVMValueRef va...@@ -2452,17 +2137,14 @@ static LLVMValueRef gen_return(CodeGen *g, AstNode *source_node, LLVMValueRef va
2452 bool is_extern = g->cur_fn->type_entry->data.fn.fn_type_id.is_extern;2137 bool is_extern = g->cur_fn->type_entry->data.fn.fn_type_id.is_extern;
2453 if (handle_is_ptr(return_type)) {2138 if (handle_is_ptr(return_type)) {
2454 if (is_extern) {2139 if (is_extern) {
2455 set_debug_source_node(g, source_node);
2456 LLVMValueRef by_val_value = LLVMBuildLoad(g->builder, value, "");2140 LLVMValueRef by_val_value = LLVMBuildLoad(g->builder, value, "");
2457 LLVMBuildRet(g->builder, by_val_value);2141 LLVMBuildRet(g->builder, by_val_value);
2458 } else {2142 } else {
2459 assert(g->cur_ret_ptr);2143 assert(g->cur_ret_ptr);
2460 gen_assign_raw(g, source_node, BinOpTypeAssign, g->cur_ret_ptr, value, return_type, return_type);2144 gen_assign_raw(g, source_node, BinOpTypeAssign, g->cur_ret_ptr, value, return_type, return_type);
2461 set_debug_source_node(g, source_node);
2462 LLVMBuildRetVoid(g->builder);2145 LLVMBuildRetVoid(g->builder);
2463 }2146 }
2464 } else {2147 } else {
2465 set_debug_source_node(g, source_node);
2466 LLVMBuildRet(g->builder, value);2148 LLVMBuildRet(g->builder, value);
2467 }2149 }
2468 return nullptr;2150 return nullptr;
...@@ -2504,7 +2186,6 @@ static LLVMValueRef gen_return_expr(CodeGen *g, AstNode *node) {...@@ -2504,7 +2186,6 @@ static LLVMValueRef gen_return_expr(CodeGen *g, AstNode *node) {
2504 LLVMBasicBlockRef return_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "ErrRetReturn");2186 LLVMBasicBlockRef return_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "ErrRetReturn");
2505 LLVMBasicBlockRef continue_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "ErrRetContinue");2187 LLVMBasicBlockRef continue_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "ErrRetContinue");
25062188
2507 set_debug_source_node(g, node);
2508 LLVMValueRef err_val;2189 LLVMValueRef err_val;
2509 if (type_has_bits(child_type)) {2190 if (type_has_bits(child_type)) {
2510 LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, value, 0, "");2191 LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, value, 0, "");
...@@ -2524,7 +2205,6 @@ static LLVMValueRef gen_return_expr(CodeGen *g, AstNode *node) {...@@ -2524,7 +2205,6 @@ static LLVMValueRef gen_return_expr(CodeGen *g, AstNode *node) {
2524 if (type_has_bits(return_type->data.error.child_type)) {2205 if (type_has_bits(return_type->data.error.child_type)) {
2525 assert(g->cur_ret_ptr);2206 assert(g->cur_ret_ptr);
25262207
2527 set_debug_source_node(g, node);
2528 LLVMValueRef tag_ptr = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, 0, "");2208 LLVMValueRef tag_ptr = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, 0, "");
2529 LLVMBuildStore(g->builder, err_val, tag_ptr);2209 LLVMBuildStore(g->builder, err_val, tag_ptr);
2530 LLVMBuildRetVoid(g->builder);2210 LLVMBuildRetVoid(g->builder);
...@@ -2537,9 +2217,8 @@ static LLVMValueRef gen_return_expr(CodeGen *g, AstNode *node) {...@@ -2537,9 +2217,8 @@ static LLVMValueRef gen_return_expr(CodeGen *g, AstNode *node) {
25372217
2538 LLVMPositionBuilderAtEnd(g->builder, continue_block);2218 LLVMPositionBuilderAtEnd(g->builder, continue_block);
2539 if (type_has_bits(child_type)) {2219 if (type_has_bits(child_type)) {
2540 set_debug_source_node(g, node);
2541 LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, value, 1, "");2220 LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, value, 1, "");
2542 return get_handle_value(g, node, val_ptr, child_type);2221 return get_handle_value(g, val_ptr, child_type);
2543 } else {2222 } else {
2544 return nullptr;2223 return nullptr;
2545 }2224 }
...@@ -2552,7 +2231,6 @@ static LLVMValueRef gen_return_expr(CodeGen *g, AstNode *node) {...@@ -2552,7 +2231,6 @@ static LLVMValueRef gen_return_expr(CodeGen *g, AstNode *node) {
2552 LLVMBasicBlockRef return_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "MaybeRetReturn");2231 LLVMBasicBlockRef return_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "MaybeRetReturn");
2553 LLVMBasicBlockRef continue_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "MaybeRetContinue");2232 LLVMBasicBlockRef continue_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "MaybeRetContinue");
25542233
2555 set_debug_source_node(g, node);
2556 LLVMValueRef maybe_val_ptr = LLVMBuildStructGEP(g->builder, value, 1, "");2234 LLVMValueRef maybe_val_ptr = LLVMBuildStructGEP(g->builder, value, 1, "");
2557 LLVMValueRef is_non_null = LLVMBuildLoad(g->builder, maybe_val_ptr, "");2235 LLVMValueRef is_non_null = LLVMBuildLoad(g->builder, maybe_val_ptr, "");
25582236
...@@ -2566,7 +2244,6 @@ static LLVMValueRef gen_return_expr(CodeGen *g, AstNode *node) {...@@ -2566,7 +2244,6 @@ static LLVMValueRef gen_return_expr(CodeGen *g, AstNode *node) {
2566 if (handle_is_ptr(return_type)) {2244 if (handle_is_ptr(return_type)) {
2567 assert(g->cur_ret_ptr);2245 assert(g->cur_ret_ptr);
25682246
2569 set_debug_source_node(g, node);
2570 LLVMValueRef maybe_bit_ptr = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, 1, "");2247 LLVMValueRef maybe_bit_ptr = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, 1, "");
2571 LLVMBuildStore(g->builder, zero, maybe_bit_ptr);2248 LLVMBuildStore(g->builder, zero, maybe_bit_ptr);
2572 LLVMBuildRetVoid(g->builder);2249 LLVMBuildRetVoid(g->builder);
...@@ -2577,9 +2254,8 @@ static LLVMValueRef gen_return_expr(CodeGen *g, AstNode *node) {...@@ -2577,9 +2254,8 @@ static LLVMValueRef gen_return_expr(CodeGen *g, AstNode *node) {
25772254
2578 LLVMPositionBuilderAtEnd(g->builder, continue_block);2255 LLVMPositionBuilderAtEnd(g->builder, continue_block);
2579 if (type_has_bits(child_type)) {2256 if (type_has_bits(child_type)) {
2580 set_debug_source_node(g, node);
2581 LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, value, 0, "");2257 LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, value, 0, "");
2582 return get_handle_value(g, node, val_ptr, child_type);2258 return get_handle_value(g, val_ptr, child_type);
2583 } else {2259 } else {
2584 return nullptr;2260 return nullptr;
2585 }2261 }
...@@ -2610,7 +2286,6 @@ static LLVMValueRef gen_if_bool_expr_raw(CodeGen *g, AstNode *source_node, LLVMV...@@ -2610,7 +2286,6 @@ static LLVMValueRef gen_if_bool_expr_raw(CodeGen *g, AstNode *source_node, LLVMV
2610 endif_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "EndIf");2286 endif_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "EndIf");
2611 }2287 }
26122288
2613 set_debug_source_node(g, source_node);
2614 LLVMBuildCondBr(g->builder, cond_value, then_block, else_block);2289 LLVMBuildCondBr(g->builder, cond_value, then_block, else_block);
26152290
2616 LLVMPositionBuilderAtEnd(g->builder, then_block);2291 LLVMPositionBuilderAtEnd(g->builder, then_block);
...@@ -2632,7 +2307,6 @@ static LLVMValueRef gen_if_bool_expr_raw(CodeGen *g, AstNode *source_node, LLVMV...@@ -2632,7 +2307,6 @@ static LLVMValueRef gen_if_bool_expr_raw(CodeGen *g, AstNode *source_node, LLVMV
2632 if (then_endif_reachable || else_endif_reachable) {2307 if (then_endif_reachable || else_endif_reachable) {
2633 LLVMPositionBuilderAtEnd(g->builder, endif_block);2308 LLVMPositionBuilderAtEnd(g->builder, endif_block);
2634 if (use_then_value && use_else_value) {2309 if (use_then_value && use_else_value) {
2635 set_debug_source_node(g, source_node);
2636 LLVMValueRef phi = LLVMBuildPhi(g->builder, LLVMTypeOf(then_expr_result), "");2310 LLVMValueRef phi = LLVMBuildPhi(g->builder, LLVMTypeOf(then_expr_result), "");
2637 LLVMValueRef incoming_values[2] = {then_expr_result, else_expr_result};2311 LLVMValueRef incoming_values[2] = {then_expr_result, else_expr_result};
2638 LLVMBasicBlockRef incoming_blocks[2] = {after_then_block, after_else_block};2312 LLVMBasicBlockRef incoming_blocks[2] = {after_then_block, after_else_block};
...@@ -2697,7 +2371,7 @@ static LLVMValueRef gen_if_var_then_block(CodeGen *g, AstNode *node, VariableTab...@@ -2697,7 +2371,7 @@ static LLVMValueRef gen_if_var_then_block(CodeGen *g, AstNode *node, VariableTab
2697 payload_val = init_val;2371 payload_val = init_val;
2698 } else {2372 } else {
2699 LLVMValueRef payload_ptr = LLVMBuildStructGEP(g->builder, init_val, 0, "");2373 LLVMValueRef payload_ptr = LLVMBuildStructGEP(g->builder, init_val, 0, "");
2700 payload_val = get_handle_value(g, node, payload_ptr, child_type);2374 payload_val = get_handle_value(g, payload_ptr, child_type);
2701 }2375 }
2702 gen_assign_raw(g, node, BinOpTypeAssign, variable->value_ref, payload_val,2376 gen_assign_raw(g, node, BinOpTypeAssign, variable->value_ref, payload_val,
2703 variable->type, child_type);2377 variable->type, child_type);
...@@ -2736,10 +2410,8 @@ static LLVMValueRef gen_if_var_expr(CodeGen *g, AstNode *node) {...@@ -2736,10 +2410,8 @@ static LLVMValueRef gen_if_var_expr(CodeGen *g, AstNode *node) {
27362410
2737 LLVMValueRef cond_value;2411 LLVMValueRef cond_value;
2738 if (maybe_is_ptr) {2412 if (maybe_is_ptr) {
2739 set_debug_source_node(g, node);
2740 cond_value = LLVMBuildICmp(g->builder, LLVMIntNE, init_val, LLVMConstNull(child_type->type_ref), "");2413 cond_value = LLVMBuildICmp(g->builder, LLVMIntNE, init_val, LLVMConstNull(child_type->type_ref), "");
2741 } else {2414 } else {
2742 set_debug_source_node(g, node);
2743 LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP(g->builder, init_val, 1, "");2415 LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP(g->builder, init_val, 1, "");
2744 cond_value = LLVMBuildLoad(g->builder, maybe_field_ptr, "");2416 cond_value = LLVMBuildLoad(g->builder, maybe_field_ptr, "");
2745 }2417 }
...@@ -2760,7 +2432,6 @@ static LLVMValueRef gen_if_var_expr(CodeGen *g, AstNode *node) {...@@ -2760,7 +2432,6 @@ static LLVMValueRef gen_if_var_expr(CodeGen *g, AstNode *node) {
2760 endif_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "MaybeEndIf");2432 endif_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "MaybeEndIf");
2761 }2433 }
27622434
2763 set_debug_source_node(g, node);
2764 LLVMBuildCondBr(g->builder, cond_value, then_block, else_block);2435 LLVMBuildCondBr(g->builder, cond_value, then_block, else_block);
27652436
2766 LLVMPositionBuilderAtEnd(g->builder, then_block);2437 LLVMPositionBuilderAtEnd(g->builder, then_block);
...@@ -2810,7 +2481,7 @@ static LLVMValueRef ir_render_load_var(CodeGen *g, IrExecutable *executable,...@@ -2810,7 +2481,7 @@ static LLVMValueRef ir_render_load_var(CodeGen *g, IrExecutable *executable,
2810 return nullptr;2481 return nullptr;
28112482
2812 assert(var->value_ref);2483 assert(var->value_ref);
2813 return get_handle_value(g, load_var_instruction->base.source_node, var->value_ref, var->type);2484 return get_handle_value(g, var->value_ref, var->type);
2814}2485}
28152486
2816static LLVMValueRef ir_render_bin_op_bool(CodeGen *g, IrExecutable *executable,2487static LLVMValueRef ir_render_bin_op_bool(CodeGen *g, IrExecutable *executable,
...@@ -2894,6 +2565,233 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,...@@ -2894,6 +2565,233 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
2894 zig_unreachable();2565 zig_unreachable();
2895}2566}
28962567
2568static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
2569 IrInstructionCast *cast_instruction)
2570{
2571 TypeTableEntry *actual_type = cast_instruction->value->type_entry;
2572 TypeTableEntry *wanted_type = cast_instruction->base.type_entry;
2573 LLVMValueRef expr_val = cast_instruction->value->llvm_value;
2574 assert(expr_val);
2575
2576 switch (cast_instruction->cast_op) {
2577 case CastOpNoCast:
2578 zig_unreachable();
2579 case CastOpNoop:
2580 return expr_val;
2581 case CastOpErrToInt:
2582 assert(actual_type->id == TypeTableEntryIdErrorUnion);
2583 if (!type_has_bits(actual_type->data.error.child_type)) {
2584 return gen_widen_or_shorten(g, cast_instruction->base.source_node,
2585 g->err_tag_type, wanted_type, expr_val);
2586 } else {
2587 zig_panic("TODO");
2588 }
2589 case CastOpMaybeWrap:
2590 {
2591 assert(cast_instruction->tmp_ptr);
2592 assert(wanted_type->id == TypeTableEntryIdMaybe);
2593 assert(actual_type);
2594
2595 TypeTableEntry *child_type = wanted_type->data.maybe.child_type;
2596
2597 if (child_type->id == TypeTableEntryIdPointer ||
2598 child_type->id == TypeTableEntryIdFn)
2599 {
2600 return expr_val;
2601 } else {
2602 LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr, 0, "");
2603 gen_assign_raw(g, cast_instruction->base.source_node, BinOpTypeAssign,
2604 val_ptr, expr_val, child_type, actual_type);
2605
2606 LLVMValueRef maybe_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr, 1, "");
2607 LLVMBuildStore(g->builder, LLVMConstAllOnes(LLVMInt1Type()), maybe_ptr);
2608 }
2609
2610 return cast_instruction->tmp_ptr;
2611 }
2612 case CastOpNullToMaybe:
2613 // handled by constant expression evaluator
2614 zig_unreachable();
2615 case CastOpErrorWrap:
2616 {
2617 assert(wanted_type->id == TypeTableEntryIdErrorUnion);
2618 TypeTableEntry *child_type = wanted_type->data.error.child_type;
2619 LLVMValueRef ok_err_val = LLVMConstNull(g->err_tag_type->type_ref);
2620
2621 if (!type_has_bits(child_type)) {
2622 return ok_err_val;
2623 } else {
2624 assert(cast_instruction->tmp_ptr);
2625 assert(wanted_type->id == TypeTableEntryIdErrorUnion);
2626 assert(actual_type);
2627
2628 LLVMValueRef err_tag_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr, 0, "");
2629 LLVMBuildStore(g->builder, ok_err_val, err_tag_ptr);
2630
2631 LLVMValueRef payload_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr, 1, "");
2632 gen_assign_raw(g, cast_instruction->base.source_node, BinOpTypeAssign,
2633 payload_ptr, expr_val, child_type, actual_type);
2634
2635 return cast_instruction->tmp_ptr;
2636 }
2637 }
2638 case CastOpPureErrorWrap:
2639 assert(wanted_type->id == TypeTableEntryIdErrorUnion);
2640
2641 if (!type_has_bits(wanted_type->data.error.child_type)) {
2642 return expr_val;
2643 } else {
2644 zig_panic("TODO");
2645 }
2646 case CastOpPtrToInt:
2647 return LLVMBuildPtrToInt(g->builder, expr_val, wanted_type->type_ref, "");
2648 case CastOpIntToPtr:
2649 return LLVMBuildIntToPtr(g->builder, expr_val, wanted_type->type_ref, "");
2650 case CastOpPointerReinterpret:
2651 return LLVMBuildBitCast(g->builder, expr_val, wanted_type->type_ref, "");
2652 case CastOpWidenOrShorten:
2653 return gen_widen_or_shorten(g, cast_instruction->base.source_node, actual_type, wanted_type, expr_val);
2654 case CastOpToUnknownSizeArray:
2655 {
2656 assert(cast_instruction->tmp_ptr);
2657 assert(wanted_type->id == TypeTableEntryIdStruct);
2658 assert(wanted_type->data.structure.is_slice);
2659
2660 TypeTableEntry *pointer_type = wanted_type->data.structure.fields[0].type_entry;
2661
2662
2663 size_t ptr_index = wanted_type->data.structure.fields[0].gen_index;
2664 if (ptr_index != SIZE_MAX) {
2665 LLVMValueRef ptr_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr, ptr_index, "");
2666 LLVMValueRef expr_bitcast = LLVMBuildBitCast(g->builder, expr_val, pointer_type->type_ref, "");
2667 LLVMBuildStore(g->builder, expr_bitcast, ptr_ptr);
2668 }
2669
2670 size_t len_index = wanted_type->data.structure.fields[1].gen_index;
2671 LLVMValueRef len_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr, len_index, "");
2672 LLVMValueRef len_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref,
2673 actual_type->data.array.len, false);
2674 LLVMBuildStore(g->builder, len_val, len_ptr);
2675
2676 return cast_instruction->tmp_ptr;
2677 }
2678 case CastOpResizeSlice:
2679 {
2680 assert(cast_instruction->tmp_ptr);
2681 assert(wanted_type->id == TypeTableEntryIdStruct);
2682 assert(wanted_type->data.structure.is_slice);
2683 assert(actual_type->id == TypeTableEntryIdStruct);
2684 assert(actual_type->data.structure.is_slice);
2685
2686 TypeTableEntry *actual_pointer_type = actual_type->data.structure.fields[0].type_entry;
2687 TypeTableEntry *actual_child_type = actual_pointer_type->data.pointer.child_type;
2688 TypeTableEntry *wanted_pointer_type = wanted_type->data.structure.fields[0].type_entry;
2689 TypeTableEntry *wanted_child_type = wanted_pointer_type->data.pointer.child_type;
2690
2691
2692 size_t actual_ptr_index = actual_type->data.structure.fields[0].gen_index;
2693 size_t actual_len_index = actual_type->data.structure.fields[1].gen_index;
2694 size_t wanted_ptr_index = wanted_type->data.structure.fields[0].gen_index;
2695 size_t wanted_len_index = wanted_type->data.structure.fields[1].gen_index;
2696
2697 LLVMValueRef src_ptr_ptr = LLVMBuildStructGEP(g->builder, expr_val, actual_ptr_index, "");
2698 LLVMValueRef src_ptr = LLVMBuildLoad(g->builder, src_ptr_ptr, "");
2699 LLVMValueRef src_ptr_casted = LLVMBuildBitCast(g->builder, src_ptr,
2700 wanted_type->data.structure.fields[0].type_entry->type_ref, "");
2701 LLVMValueRef dest_ptr_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr,
2702 wanted_ptr_index, "");
2703 LLVMBuildStore(g->builder, src_ptr_casted, dest_ptr_ptr);
2704
2705 LLVMValueRef src_len_ptr = LLVMBuildStructGEP(g->builder, expr_val, actual_len_index, "");
2706 LLVMValueRef src_len = LLVMBuildLoad(g->builder, src_len_ptr, "");
2707 uint64_t src_size = type_size(g, actual_child_type);
2708 uint64_t dest_size = type_size(g, wanted_child_type);
2709
2710 LLVMValueRef new_len;
2711 if (dest_size == 1) {
2712 LLVMValueRef src_size_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref, src_size, false);
2713 new_len = LLVMBuildMul(g->builder, src_len, src_size_val, "");
2714 } else if (src_size == 1) {
2715 LLVMValueRef dest_size_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref, dest_size, false);
2716 if (ir_want_debug_safety(g, &cast_instruction->base)) {
2717 LLVMValueRef remainder_val = LLVMBuildURem(g->builder, src_len, dest_size_val, "");
2718 LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_usize->type_ref);
2719 LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, remainder_val, zero, "");
2720 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "SliceWidenOk");
2721 LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "SliceWidenFail");
2722 LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block);
2723
2724 LLVMPositionBuilderAtEnd(g->builder, fail_block);
2725 gen_debug_safety_crash(g);
2726
2727 LLVMPositionBuilderAtEnd(g->builder, ok_block);
2728 }
2729 new_len = ZigLLVMBuildExactUDiv(g->builder, src_len, dest_size_val, "");
2730 } else {
2731 zig_unreachable();
2732 }
2733
2734 LLVMValueRef dest_len_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr,
2735 wanted_len_index, "");
2736 LLVMBuildStore(g->builder, new_len, dest_len_ptr);
2737
2738
2739 return cast_instruction->tmp_ptr;
2740 }
2741 case CastOpBytesToSlice:
2742 {
2743 assert(cast_instruction->tmp_ptr);
2744 assert(wanted_type->id == TypeTableEntryIdStruct);
2745 assert(wanted_type->data.structure.is_slice);
2746 assert(actual_type->id == TypeTableEntryIdArray);
2747
2748 TypeTableEntry *wanted_pointer_type = wanted_type->data.structure.fields[0].type_entry;
2749 TypeTableEntry *wanted_child_type = wanted_pointer_type->data.pointer.child_type;
2750
2751
2752 size_t wanted_ptr_index = wanted_type->data.structure.fields[0].gen_index;
2753 LLVMValueRef dest_ptr_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr, wanted_ptr_index, "");
2754 LLVMValueRef src_ptr_casted = LLVMBuildBitCast(g->builder, expr_val, wanted_pointer_type->type_ref, "");
2755 LLVMBuildStore(g->builder, src_ptr_casted, dest_ptr_ptr);
2756
2757 size_t wanted_len_index = wanted_type->data.structure.fields[1].gen_index;
2758 LLVMValueRef len_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr, wanted_len_index, "");
2759 LLVMValueRef len_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref,
2760 actual_type->data.array.len / type_size(g, wanted_child_type), false);
2761 LLVMBuildStore(g->builder, len_val, len_ptr);
2762
2763 return cast_instruction->tmp_ptr;
2764 }
2765 case CastOpIntToFloat:
2766 assert(actual_type->id == TypeTableEntryIdInt);
2767 if (actual_type->data.integral.is_signed) {
2768 return LLVMBuildSIToFP(g->builder, expr_val, wanted_type->type_ref, "");
2769 } else {
2770 return LLVMBuildUIToFP(g->builder, expr_val, wanted_type->type_ref, "");
2771 }
2772 case CastOpFloatToInt:
2773 assert(wanted_type->id == TypeTableEntryIdInt);
2774 if (wanted_type->data.integral.is_signed) {
2775 return LLVMBuildFPToSI(g->builder, expr_val, wanted_type->type_ref, "");
2776 } else {
2777 return LLVMBuildFPToUI(g->builder, expr_val, wanted_type->type_ref, "");
2778 }
2779
2780 case CastOpBoolToInt:
2781 assert(wanted_type->id == TypeTableEntryIdInt);
2782 assert(actual_type->id == TypeTableEntryIdBool);
2783 return LLVMBuildZExt(g->builder, expr_val, wanted_type->type_ref, "");
2784
2785 case CastOpIntToEnum:
2786 return gen_widen_or_shorten(g, cast_instruction->base.source_node,
2787 actual_type, wanted_type->data.enumeration.tag_type, expr_val);
2788 case CastOpEnumToInt:
2789 return gen_widen_or_shorten(g, cast_instruction->base.source_node,
2790 actual_type->data.enumeration.tag_type, wanted_type, expr_val);
2791 }
2792 zig_unreachable();
2793}
2794
2897static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, IrInstruction *instruction) {2795static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, IrInstruction *instruction) {
2898 set_debug_source_node(g, instruction->source_node);2796 set_debug_source_node(g, instruction->source_node);
2899 switch (instruction->id) {2797 switch (instruction->id) {
...@@ -2907,13 +2805,14 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -2907,13 +2805,14 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
2907 return ir_render_load_var(g, executable, (IrInstructionLoadVar *)instruction);2805 return ir_render_load_var(g, executable, (IrInstructionLoadVar *)instruction);
2908 case IrInstructionIdBinOp:2806 case IrInstructionIdBinOp:
2909 return ir_render_bin_op(g, executable, (IrInstructionBinOp *)instruction);2807 return ir_render_bin_op(g, executable, (IrInstructionBinOp *)instruction);
2808 case IrInstructionIdCast:
2809 return ir_render_cast(g, executable, (IrInstructionCast *)instruction);
2910 case IrInstructionIdCondBr:2810 case IrInstructionIdCondBr:
2911 case IrInstructionIdSwitchBr:2811 case IrInstructionIdSwitchBr:
2912 case IrInstructionIdPhi:2812 case IrInstructionIdPhi:
2913 case IrInstructionIdStoreVar:2813 case IrInstructionIdStoreVar:
2914 case IrInstructionIdCall:2814 case IrInstructionIdCall:
2915 case IrInstructionIdBuiltinCall:2815 case IrInstructionIdBuiltinCall:
2916 case IrInstructionIdCast:
2917 zig_panic("TODO render more IR instructions to LLVM");2816 zig_panic("TODO render more IR instructions to LLVM");
2918 }2817 }
2919 zig_unreachable();2818 zig_unreachable();
...@@ -3592,7 +3491,7 @@ static LLVMValueRef gen_switch_expr(CodeGen *g, AstNode *node) {...@@ -3592,7 +3491,7 @@ static LLVMValueRef gen_switch_expr(CodeGen *g, AstNode *node) {
3592 1, "");3491 1, "");
3593 LLVMValueRef bitcasted_union_field_ptr = LLVMBuildBitCast(g->builder, union_field_ptr,3492 LLVMValueRef bitcasted_union_field_ptr = LLVMBuildBitCast(g->builder, union_field_ptr,
3594 LLVMPointerType(enum_field->type_entry->type_ref, 0), "");3493 LLVMPointerType(enum_field->type_entry->type_ref, 0), "");
3595 LLVMValueRef handle_val = get_handle_value(g, var_node, bitcasted_union_field_ptr,3494 LLVMValueRef handle_val = get_handle_value(g, bitcasted_union_field_ptr,
3596 enum_field->type_entry);3495 enum_field->type_entry);
35973496
3598 gen_assign_raw(g, var_node, BinOpTypeAssign,3497 gen_assign_raw(g, var_node, BinOpTypeAssign,
...@@ -3602,8 +3501,7 @@ static LLVMValueRef gen_switch_expr(CodeGen *g, AstNode *node) {...@@ -3602,8 +3501,7 @@ static LLVMValueRef gen_switch_expr(CodeGen *g, AstNode *node) {
3602 // variable is the payload3501 // variable is the payload
3603 LLVMValueRef err_payload_ptr = LLVMBuildStructGEP(g->builder,3502 LLVMValueRef err_payload_ptr = LLVMBuildStructGEP(g->builder,
3604 target_value_handle, 1, "");3503 target_value_handle, 1, "");
3605 LLVMValueRef handle_val = get_handle_value(g, var_node,3504 LLVMValueRef handle_val = get_handle_value(g, err_payload_ptr, prong_var->type);
3606 err_payload_ptr, prong_var->type);
3607 gen_assign_raw(g, var_node, BinOpTypeAssign,3505 gen_assign_raw(g, var_node, BinOpTypeAssign,
3608 prong_var->value_ref, handle_val, prong_var->type, prong_var->type);3506 prong_var->value_ref, handle_val, prong_var->type, prong_var->type);
3609 } else {3507 } else {
...@@ -4375,10 +4273,8 @@ static void do_code_gen(CodeGen *g) {...@@ -4375,10 +4273,8 @@ static void do_code_gen(CodeGen *g) {
43754273
4376 // allocate structs which are the result of casts4274 // allocate structs which are the result of casts
4377 for (size_t cea_i = 0; cea_i < fn_table_entry->cast_alloca_list.length; cea_i += 1) {4275 for (size_t cea_i = 0; cea_i < fn_table_entry->cast_alloca_list.length; cea_i += 1) {
4378 AstNode *fn_call_node = fn_table_entry->cast_alloca_list.at(cea_i);4276 IrInstructionCast *cast_instruction = fn_table_entry->cast_alloca_list.at(cea_i);
4379 Expr *expr = &fn_call_node->data.fn_call_expr.resolved_expr;4277 cast_instruction->tmp_ptr = LLVMBuildAlloca(g->builder, cast_instruction->base.type_entry->type_ref, "");
4380 fn_call_node->data.fn_call_expr.tmp_ptr = LLVMBuildAlloca(g->builder,
4381 expr->type_entry->type_ref, "");
4382 }4278 }
43834279
4384 // allocate structs which are struct value expressions4280 // allocate structs which are struct value expressions
src/eval.cpp+1
...@@ -773,6 +773,7 @@ void eval_const_expr_implicit_cast(CastOp cast_op,...@@ -773,6 +773,7 @@ void eval_const_expr_implicit_cast(CastOp cast_op,
773 case CastOpEnumToInt:773 case CastOpEnumToInt:
774 bignum_init_unsigned(&const_val->data.x_bignum, other_val->data.x_enum.tag);774 bignum_init_unsigned(&const_val->data.x_bignum, other_val->data.x_enum.tag);
775 const_val->ok = true;775 const_val->ok = true;
776 break;
776 }777 }
777}778}
778779
src/ir.cpp+530-15
...@@ -1,6 +1,7 @@...@@ -1,6 +1,7 @@
1#include "analyze.hpp"1#include "analyze.hpp"
2#include "ir.hpp"
3#include "error.hpp"2#include "error.hpp"
3#include "eval.hpp"
4#include "ir.hpp"
45
5struct IrVarSlot {6struct IrVarSlot {
6 ConstExprValue value;7 ConstExprValue value;
...@@ -100,12 +101,12 @@ static T *ir_build_instruction(IrBuilder *irb, AstNode *source_node) {...@@ -100,12 +101,12 @@ static T *ir_build_instruction(IrBuilder *irb, AstNode *source_node) {
100}101}
101102
102static IrInstruction *ir_build_cast(IrBuilder *irb, AstNode *source_node, IrInstruction *dest_type,103static IrInstruction *ir_build_cast(IrBuilder *irb, AstNode *source_node, IrInstruction *dest_type,
103 IrInstruction *value, bool is_implicit)104 IrInstruction *value, CastOp cast_op)
104{105{
105 IrInstructionCast *cast_instruction = ir_build_instruction<IrInstructionCast>(irb, source_node);106 IrInstructionCast *cast_instruction = ir_build_instruction<IrInstructionCast>(irb, source_node);
106 cast_instruction->dest_type = dest_type;107 cast_instruction->dest_type = dest_type;
107 cast_instruction->value = value;108 cast_instruction->value = value;
108 cast_instruction->is_implicit = is_implicit;109 cast_instruction->cast_op = cast_op;
109 return &cast_instruction->base;110 return &cast_instruction->base;
110}111}
111112
...@@ -117,6 +118,13 @@ static IrInstruction *ir_build_return(IrBuilder *irb, AstNode *source_node, IrIn...@@ -117,6 +118,13 @@ static IrInstruction *ir_build_return(IrBuilder *irb, AstNode *source_node, IrIn
117 return &return_instruction->base;118 return &return_instruction->base;
118}119}
119120
121static IrInstruction *ir_build_const(IrBuilder *irb, AstNode *source_node, TypeTableEntry *type_entry) {
122 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node);
123 const_instruction->base.type_entry = type_entry;
124 const_instruction->base.static_value.ok = true;
125 return &const_instruction->base;
126}
127
120static IrInstruction *ir_build_const_void(IrBuilder *irb, AstNode *source_node) {128static IrInstruction *ir_build_const_void(IrBuilder *irb, AstNode *source_node) {
121 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node);129 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node);
122 const_instruction->base.type_entry = irb->codegen->builtin_types.entry_void;130 const_instruction->base.type_entry = irb->codegen->builtin_types.entry_void;
...@@ -133,14 +141,20 @@ static IrInstruction *ir_build_const_bignum(IrBuilder *irb, AstNode *source_node...@@ -133,14 +141,20 @@ static IrInstruction *ir_build_const_bignum(IrBuilder *irb, AstNode *source_node
133 return &const_instruction->base;141 return &const_instruction->base;
134}142}
135143
136static IrInstruction *ir_build_const_type(IrBuilder *irb, AstNode *source_node, TypeTableEntry *type_entry) {144static IrInstruction *ir_create_const_type(IrBuilder *irb, AstNode *source_node, TypeTableEntry *type_entry) {
137 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node);145 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(irb->exec, source_node);
138 const_instruction->base.type_entry = irb->codegen->builtin_types.entry_type;146 const_instruction->base.type_entry = irb->codegen->builtin_types.entry_type;
139 const_instruction->base.static_value.ok = true;147 const_instruction->base.static_value.ok = true;
140 const_instruction->base.static_value.data.x_type = type_entry;148 const_instruction->base.static_value.data.x_type = type_entry;
141 return &const_instruction->base;149 return &const_instruction->base;
142}150}
143151
152static IrInstruction *ir_build_const_type(IrBuilder *irb, AstNode *source_node, TypeTableEntry *type_entry) {
153 IrInstruction *instruction = ir_create_const_type(irb, source_node, type_entry);
154 ir_instruction_append(irb->current_basic_block, instruction);
155 return instruction;
156}
157
144static IrInstruction *ir_build_const_fn(IrBuilder *irb, AstNode *source_node, FnTableEntry *fn_entry) {158static IrInstruction *ir_build_const_fn(IrBuilder *irb, AstNode *source_node, FnTableEntry *fn_entry) {
145 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node);159 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node);
146 const_instruction->base.type_entry = fn_entry->type_entry;160 const_instruction->base.type_entry = fn_entry->type_entry;
...@@ -174,6 +188,16 @@ static IrInstruction *ir_build_load_var(IrBuilder *irb, AstNode *source_node, Va...@@ -174,6 +188,16 @@ static IrInstruction *ir_build_load_var(IrBuilder *irb, AstNode *source_node, Va
174 return &load_var_instruction->base;188 return &load_var_instruction->base;
175}189}
176190
191static IrInstruction *ir_build_call(IrBuilder *irb, AstNode *source_node,
192 IrInstruction *fn, size_t arg_count, IrInstruction **args)
193{
194 IrInstructionCall *call_instruction = ir_build_instruction<IrInstructionCall>(irb, source_node);
195 call_instruction->fn = fn;
196 call_instruction->arg_count = arg_count;
197 call_instruction->args = args;
198 return &call_instruction->base;
199}
200
177201
178//static size_t get_conditional_defer_count(BlockContext *inner_block, BlockContext *outer_block) {202//static size_t get_conditional_defer_count(BlockContext *inner_block, BlockContext *outer_block) {
179// size_t result = 0;203// size_t result = 0;
...@@ -409,6 +433,26 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, AstNode *node, bool pointer_...@@ -409,6 +433,26 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, AstNode *node, bool pointer_
409 return irb->codegen->invalid_instruction;433 return irb->codegen->invalid_instruction;
410}434}
411435
436static IrInstruction *ir_gen_fn_call(IrBuilder *irb, AstNode *node) {
437 assert(node->type == NodeTypeFnCallExpr);
438
439 if (node->data.fn_call_expr.is_builtin) {
440 zig_panic("TODO ir gen builtin fn");
441 }
442
443 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);
445
446 size_t arg_count = node->data.fn_call_expr.params.length;
447 IrInstruction **args = allocate<IrInstruction*>(arg_count);
448 for (size_t i = 0; i < arg_count; i += 1) {
449 AstNode *arg_node = node->data.fn_call_expr.params.at(i);
450 args[i] = ir_gen_node(irb, arg_node, node->block_context);
451 }
452
453 return ir_build_call(irb, node, fn, arg_count, args);
454}
455
412static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockContext *block_context,456static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockContext *block_context,
413 bool pointer_only)457 bool pointer_only)
414{458{
...@@ -423,12 +467,13 @@ static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockCont...@@ -423,12 +467,13 @@ static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockCont
423 return ir_gen_num_lit(irb, node);467 return ir_gen_num_lit(irb, node);
424 case NodeTypeSymbol:468 case NodeTypeSymbol:
425 return ir_gen_symbol(irb, node, pointer_only);469 return ir_gen_symbol(irb, node, pointer_only);
470 case NodeTypeFnCallExpr:
471 return ir_gen_fn_call(irb, node);
426 case NodeTypeUnwrapErrorExpr:472 case NodeTypeUnwrapErrorExpr:
427 case NodeTypeReturnExpr:473 case NodeTypeReturnExpr:
428 case NodeTypeDefer:474 case NodeTypeDefer:
429 case NodeTypeVariableDeclaration:475 case NodeTypeVariableDeclaration:
430 case NodeTypePrefixOpExpr:476 case NodeTypePrefixOpExpr:
431 case NodeTypeFnCallExpr:
432 case NodeTypeArrayAccessExpr:477 case NodeTypeArrayAccessExpr:
433 case NodeTypeSliceExpr:478 case NodeTypeSliceExpr:
434 case NodeTypeFieldAccessExpr:479 case NodeTypeFieldAccessExpr:
...@@ -782,6 +827,296 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, IrInstruction *pare...@@ -782,6 +827,296 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, IrInstruction *pare
782 return ir_determine_peer_types(ira, parent_instruction, instructions, instruction_count);827 return ir_determine_peer_types(ira, parent_instruction, instructions, instruction_count);
783}828}
784829
830static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
831 IrInstruction *dest_type, CastOp cast_op, bool need_alloca)
832{
833 assert(dest_type->type_entry->id == TypeTableEntryIdMetaType);
834 assert(dest_type->static_value.ok);
835 TypeTableEntry *wanted_type = dest_type->static_value.data.x_type;
836
837 if (value->static_value.ok) {
838 IrInstruction *result = ir_build_const(&ira->new_irb, source_instr->source_node, wanted_type);
839 eval_const_expr_implicit_cast(cast_op, &value->static_value, value->type_entry,
840 &result->static_value, wanted_type);
841 return result;
842 } else {
843 IrInstruction *result = ir_build_cast(&ira->new_irb, source_instr->source_node,
844 dest_type->other, value->other, cast_op);
845 result->type_entry = wanted_type;
846 if (need_alloca && source_instr->source_node->block_context->fn_entry) {
847 IrInstructionCast *cast_instruction = (IrInstructionCast *)result;
848 source_instr->source_node->block_context->fn_entry->cast_alloca_list.append(cast_instruction);
849 }
850 return result;
851 }
852}
853
854static bool is_slice(TypeTableEntry *type) {
855 return type->id == TypeTableEntryIdStruct && type->data.structure.is_slice;
856}
857
858static bool is_u8(TypeTableEntry *type) {
859 return type->id == TypeTableEntryIdInt &&
860 !type->data.integral.is_signed && type->data.integral.bit_count == 8;
861}
862
863static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr,
864 IrInstruction *dest_type, IrInstruction *value)
865{
866 assert(dest_type->type_entry->id == TypeTableEntryIdMetaType);
867 assert(dest_type->static_value.ok);
868
869 TypeTableEntry *wanted_type = dest_type->static_value.data.x_type;
870 TypeTableEntry *actual_type = value->type_entry;
871 TypeTableEntry *wanted_type_canon = get_underlying_type(wanted_type);
872 TypeTableEntry *actual_type_canon = get_underlying_type(actual_type);
873
874 TypeTableEntry *isize_type = ira->codegen->builtin_types.entry_isize;
875 TypeTableEntry *usize_type = ira->codegen->builtin_types.entry_usize;
876
877 if (wanted_type_canon->id == TypeTableEntryIdInvalid ||
878 actual_type_canon->id == TypeTableEntryIdInvalid)
879 {
880 return ira->codegen->invalid_instruction;
881 }
882
883 // explicit match or non-const to const
884 if (types_match_const_cast_only(wanted_type, actual_type)) {
885 return ir_resolve_cast(ira, source_instr, value, dest_type, CastOpNoop, false);
886 }
887
888 // explicit cast from bool to int
889 if (wanted_type_canon->id == TypeTableEntryIdInt &&
890 actual_type_canon->id == TypeTableEntryIdBool)
891 {
892 return ir_resolve_cast(ira, source_instr, value, dest_type, CastOpBoolToInt, false);
893 }
894
895 // explicit cast from pointer to isize or usize
896 if ((wanted_type_canon == isize_type || wanted_type_canon == usize_type) &&
897 type_is_codegen_pointer(actual_type_canon))
898 {
899 return ir_resolve_cast(ira, source_instr, value, dest_type, CastOpPtrToInt, false);
900 }
901
902
903 // explicit cast from isize or usize to pointer
904 if (wanted_type_canon->id == TypeTableEntryIdPointer &&
905 (actual_type_canon == isize_type || actual_type_canon == usize_type))
906 {
907 return ir_resolve_cast(ira, source_instr, value, dest_type, CastOpIntToPtr, false);
908 }
909
910 // explicit widening or shortening cast
911 if ((wanted_type_canon->id == TypeTableEntryIdInt &&
912 actual_type_canon->id == TypeTableEntryIdInt) ||
913 (wanted_type_canon->id == TypeTableEntryIdFloat &&
914 actual_type_canon->id == TypeTableEntryIdFloat))
915 {
916 return ir_resolve_cast(ira, source_instr, value, dest_type, CastOpWidenOrShorten, false);
917 }
918
919 // explicit cast from int to float
920 if (wanted_type_canon->id == TypeTableEntryIdFloat &&
921 actual_type_canon->id == TypeTableEntryIdInt)
922 {
923 return ir_resolve_cast(ira, source_instr, value, dest_type, CastOpIntToFloat, false);
924 }
925
926 // explicit cast from float to int
927 if (wanted_type_canon->id == TypeTableEntryIdInt &&
928 actual_type_canon->id == TypeTableEntryIdFloat)
929 {
930 return ir_resolve_cast(ira, source_instr, value, dest_type, CastOpFloatToInt, false);
931 }
932
933 // explicit cast from array to slice
934 if (is_slice(wanted_type) &&
935 actual_type->id == TypeTableEntryIdArray &&
936 types_match_const_cast_only(
937 wanted_type->data.structure.fields[0].type_entry->data.pointer.child_type,
938 actual_type->data.array.child_type))
939 {
940 return ir_resolve_cast(ira, source_instr, value, dest_type, CastOpToUnknownSizeArray, true);
941 }
942
943 // explicit cast from []T to []u8 or []u8 to []T
944 if (is_slice(wanted_type) && is_slice(actual_type) &&
945 (is_u8(wanted_type->data.structure.fields[0].type_entry->data.pointer.child_type) ||
946 is_u8(actual_type->data.structure.fields[0].type_entry->data.pointer.child_type)) &&
947 (wanted_type->data.structure.fields[0].type_entry->data.pointer.is_const ||
948 !actual_type->data.structure.fields[0].type_entry->data.pointer.is_const))
949 {
950 mark_impure_fn(ira->codegen, source_instr->source_node->block_context, source_instr->source_node);
951 return ir_resolve_cast(ira, source_instr, value, dest_type, CastOpResizeSlice, true);
952 }
953
954 // explicit cast from [N]u8 to []T
955 if (is_slice(wanted_type) &&
956 actual_type->id == TypeTableEntryIdArray &&
957 is_u8(actual_type->data.array.child_type))
958 {
959 mark_impure_fn(ira->codegen, source_instr->source_node->block_context, source_instr->source_node);
960 uint64_t child_type_size = type_size(ira->codegen,
961 wanted_type->data.structure.fields[0].type_entry->data.pointer.child_type);
962 if (actual_type->data.array.len % child_type_size == 0) {
963 return ir_resolve_cast(ira, source_instr, value, dest_type, CastOpBytesToSlice, true);
964 } else {
965 add_node_error(ira->codegen, source_instr->source_node,
966 buf_sprintf("unable to convert %s to %s: size mismatch",
967 buf_ptr(&actual_type->name), buf_ptr(&wanted_type->name)));
968 return ira->codegen->invalid_instruction;
969 }
970 }
971
972 // explicit cast from pointer to another pointer
973 if ((actual_type->id == TypeTableEntryIdPointer || actual_type->id == TypeTableEntryIdFn) &&
974 (wanted_type->id == TypeTableEntryIdPointer || wanted_type->id == TypeTableEntryIdFn))
975 {
976 return ir_resolve_cast(ira, source_instr, value, dest_type, CastOpPointerReinterpret, false);
977 }
978
979 // explicit cast from maybe pointer to another maybe pointer
980 if (actual_type->id == TypeTableEntryIdMaybe &&
981 (actual_type->data.maybe.child_type->id == TypeTableEntryIdPointer ||
982 actual_type->data.maybe.child_type->id == TypeTableEntryIdFn) &&
983 wanted_type->id == TypeTableEntryIdMaybe &&
984 (wanted_type->data.maybe.child_type->id == TypeTableEntryIdPointer ||
985 wanted_type->data.maybe.child_type->id == TypeTableEntryIdFn))
986 {
987 return ir_resolve_cast(ira, source_instr, value, dest_type, CastOpPointerReinterpret, false);
988 }
989
990 // explicit cast from child type of maybe type to maybe type
991 if (wanted_type->id == TypeTableEntryIdMaybe) {
992 if (types_match_const_cast_only(wanted_type->data.maybe.child_type, actual_type)) {
993 IrInstruction *cast_instruction = ir_resolve_cast(ira, source_instr, value, dest_type,
994 CastOpMaybeWrap, true);
995 cast_instruction->return_knowledge = ReturnKnowledgeKnownNonNull;
996 return cast_instruction;
997 } else if (actual_type->id == TypeTableEntryIdNumLitInt ||
998 actual_type->id == TypeTableEntryIdNumLitFloat)
999 {
1000 if (ir_num_lit_fits_in_other_type(ira, value, wanted_type->data.maybe.child_type)) {
1001 IrInstruction *cast_instruction = ir_resolve_cast(ira, source_instr, value, dest_type,
1002 CastOpMaybeWrap, true);
1003 cast_instruction->return_knowledge = ReturnKnowledgeKnownNonNull;
1004 return cast_instruction;
1005 } else {
1006 return ira->codegen->invalid_instruction;
1007 }
1008 }
1009 }
1010
1011 // explicit cast from null literal to maybe type
1012 if (wanted_type->id == TypeTableEntryIdMaybe &&
1013 actual_type->id == TypeTableEntryIdNullLit)
1014 {
1015 IrInstruction *cast_instruction = ir_resolve_cast(ira, source_instr, value, dest_type,
1016 CastOpNullToMaybe, true);
1017 cast_instruction->return_knowledge = ReturnKnowledgeKnownNull;
1018 return cast_instruction;
1019 }
1020
1021 // explicit cast from child type of error type to error type
1022 if (wanted_type->id == TypeTableEntryIdErrorUnion) {
1023 if (types_match_const_cast_only(wanted_type->data.error.child_type, actual_type)) {
1024 IrInstruction *cast_instruction = ir_resolve_cast(ira, source_instr, value, dest_type,
1025 CastOpErrorWrap, true);
1026 cast_instruction->return_knowledge = ReturnKnowledgeKnownNonError;
1027 return cast_instruction;
1028 } else if (actual_type->id == TypeTableEntryIdNumLitInt ||
1029 actual_type->id == TypeTableEntryIdNumLitFloat)
1030 {
1031 if (ir_num_lit_fits_in_other_type(ira, value, wanted_type->data.error.child_type)) {
1032 IrInstruction *cast_instruction = ir_resolve_cast(ira, source_instr, value, dest_type,
1033 CastOpErrorWrap, true);
1034 cast_instruction->return_knowledge = ReturnKnowledgeKnownNonError;
1035 return cast_instruction;
1036 } else {
1037 return ira->codegen->invalid_instruction;
1038 }
1039 }
1040 }
1041
1042 // explicit cast from pure error to error union type
1043 if (wanted_type->id == TypeTableEntryIdErrorUnion &&
1044 actual_type->id == TypeTableEntryIdPureError)
1045 {
1046 IrInstruction *cast_instruction = ir_resolve_cast(ira, source_instr, value, dest_type,
1047 CastOpPureErrorWrap, false);
1048 cast_instruction->return_knowledge = ReturnKnowledgeKnownError;
1049 return cast_instruction;
1050 }
1051
1052 // explicit cast from number literal to another type
1053 if (actual_type->id == TypeTableEntryIdNumLitFloat ||
1054 actual_type->id == TypeTableEntryIdNumLitInt)
1055 {
1056 if (ir_num_lit_fits_in_other_type(ira, value, wanted_type_canon)) {
1057 CastOp op;
1058 if ((actual_type->id == TypeTableEntryIdNumLitFloat &&
1059 wanted_type_canon->id == TypeTableEntryIdFloat) ||
1060 (actual_type->id == TypeTableEntryIdNumLitInt &&
1061 wanted_type_canon->id == TypeTableEntryIdInt))
1062 {
1063 op = CastOpNoop;
1064 } else if (wanted_type_canon->id == TypeTableEntryIdInt) {
1065 op = CastOpFloatToInt;
1066 } else if (wanted_type_canon->id == TypeTableEntryIdFloat) {
1067 op = CastOpIntToFloat;
1068 } else {
1069 zig_unreachable();
1070 }
1071 return ir_resolve_cast(ira, source_instr, value, dest_type, op, false);
1072 } else {
1073 return ira->codegen->invalid_instruction;
1074 }
1075 }
1076
1077 // explicit cast from %void to integer type which can fit it
1078 bool actual_type_is_void_err = actual_type->id == TypeTableEntryIdErrorUnion &&
1079 !type_has_bits(actual_type->data.error.child_type);
1080 bool actual_type_is_pure_err = actual_type->id == TypeTableEntryIdPureError;
1081 if ((actual_type_is_void_err || actual_type_is_pure_err) &&
1082 wanted_type->id == TypeTableEntryIdInt)
1083 {
1084 BigNum bn;
1085 bignum_init_unsigned(&bn, ira->codegen->error_decls.length);
1086 if (bignum_fits_in_bits(&bn, wanted_type->data.integral.bit_count,
1087 wanted_type->data.integral.is_signed))
1088 {
1089 return ir_resolve_cast(ira, source_instr, value, dest_type, CastOpErrToInt, false);
1090 } else {
1091 add_node_error(ira->codegen, source_instr->source_node,
1092 buf_sprintf("too many error values to fit in '%s'", buf_ptr(&wanted_type->name)));
1093 return ira->codegen->invalid_instruction;
1094 }
1095 }
1096
1097 // explicit cast from integer to enum type with no payload
1098 if (actual_type->id == TypeTableEntryIdInt &&
1099 wanted_type->id == TypeTableEntryIdEnum &&
1100 wanted_type->data.enumeration.gen_field_count == 0)
1101 {
1102 return ir_resolve_cast(ira, source_instr, value, dest_type, CastOpIntToEnum, false);
1103 }
1104
1105 // explicit cast from enum type with no payload to integer
1106 if (wanted_type->id == TypeTableEntryIdInt &&
1107 actual_type->id == TypeTableEntryIdEnum &&
1108 actual_type->data.enumeration.gen_field_count == 0)
1109 {
1110 return ir_resolve_cast(ira, source_instr, value, dest_type, CastOpEnumToInt, false);
1111 }
1112
1113 add_node_error(ira->codegen, source_instr->source_node,
1114 buf_sprintf("invalid cast from type '%s' to '%s'",
1115 buf_ptr(&actual_type->name),
1116 buf_ptr(&wanted_type->name)));
1117 return ira->codegen->invalid_instruction;
1118}
1119
785static IrInstruction *ir_get_casted_value(IrAnalyze *ira, IrInstruction *value, TypeTableEntry *expected_type) {1120static IrInstruction *ir_get_casted_value(IrAnalyze *ira, IrInstruction *value, TypeTableEntry *expected_type) {
786 assert(value);1121 assert(value);
787 assert(value != ira->old_irb.codegen->invalid_instruction);1122 assert(value != ira->old_irb.codegen->invalid_instruction);
...@@ -806,10 +1141,8 @@ static IrInstruction *ir_get_casted_value(IrAnalyze *ira, IrInstruction *value,...@@ -806,10 +1141,8 @@ static IrInstruction *ir_get_casted_value(IrAnalyze *ira, IrInstruction *value,
8061141
807 case ImplicitCastMatchResultYes:1142 case ImplicitCastMatchResultYes:
808 {1143 {
809 IrInstruction *dest_type = ir_build_const_type(&ira->new_irb, value->source_node, expected_type);1144 IrInstruction *dest_type = ir_create_const_type(&ira->new_irb, value->source_node, expected_type);
810 bool is_implicit = true;1145 IrInstruction *cast_instruction = ir_analyze_cast(ira, value, dest_type, value);
811 IrInstruction *cast_instruction = ir_build_cast(&ira->new_irb, value->source_node, dest_type,
812 value, is_implicit);
813 return cast_instruction;1146 return cast_instruction;
814 }1147 }
815 case ImplicitCastMatchResultReportedError:1148 case ImplicitCastMatchResultReportedError:
...@@ -849,18 +1182,41 @@ static TypeTableEntry *ir_analyze_bin_op_bool(IrAnalyze *ira, IrInstructionBinOp...@@ -849,18 +1182,41 @@ static TypeTableEntry *ir_analyze_bin_op_bool(IrAnalyze *ira, IrInstructionBinOp
849 IrInstruction *op1 = bin_op_instruction->op1;1182 IrInstruction *op1 = bin_op_instruction->op1;
850 IrInstruction *op2 = bin_op_instruction->op2;1183 IrInstruction *op2 = bin_op_instruction->op2;
8511184
852 IrInstruction *casted_op1 = ir_get_casted_value(ira, op1->other, ira->old_irb.codegen->builtin_types.entry_bool);1185 TypeTableEntry *bool_type = ira->old_irb.codegen->builtin_types.entry_bool;
1186
1187 IrInstruction *casted_op1 = ir_get_casted_value(ira, op1->other, bool_type);
853 if (casted_op1 == ira->old_irb.codegen->invalid_instruction)1188 if (casted_op1 == ira->old_irb.codegen->invalid_instruction)
854 return ira->old_irb.codegen->builtin_types.entry_invalid;1189 return ira->old_irb.codegen->builtin_types.entry_invalid;
8551190
856 IrInstruction *casted_op2 = ir_get_casted_value(ira, op2->other, ira->old_irb.codegen->builtin_types.entry_bool);1191 IrInstruction *casted_op2 = ir_get_casted_value(ira, op2->other, bool_type);
857 if (casted_op2 == ira->old_irb.codegen->invalid_instruction)1192 if (casted_op2 == ira->old_irb.codegen->invalid_instruction)
858 return ira->old_irb.codegen->builtin_types.entry_invalid;1193 return ira->old_irb.codegen->builtin_types.entry_invalid;
8591194
1195 ConstExprValue *op1_val = &casted_op1->static_value;
1196 ConstExprValue *op2_val = &casted_op2->static_value;
1197 if (op1_val->ok && op2_val->ok) {
1198 ConstExprValue *out_val = &bin_op_instruction->base.static_value;
1199 bin_op_instruction->base.other = &bin_op_instruction->base;
1200
1201 assert(op1->type_entry->id == TypeTableEntryIdBool);
1202 assert(op2->type_entry->id == TypeTableEntryIdBool);
1203 if (bin_op_instruction->op_id == IrBinOpBoolOr) {
1204 out_val->data.x_bool = op1_val->data.x_bool || op2_val->data.x_bool;
1205 } else if (bin_op_instruction->op_id == IrBinOpBoolAnd) {
1206 out_val->data.x_bool = op1_val->data.x_bool && op2_val->data.x_bool;
1207 } else {
1208 zig_unreachable();
1209 }
1210 out_val->ok = true;
1211 out_val->depends_on_compile_var = op1_val->depends_on_compile_var ||
1212 op2_val->depends_on_compile_var;
1213 return bool_type;
1214 }
1215
860 ir_link_new(ir_build_bin_op(&ira->new_irb, bin_op_instruction->base.source_node,1216 ir_link_new(ir_build_bin_op(&ira->new_irb, bin_op_instruction->base.source_node,
861 bin_op_instruction->op_id, op1->other, op2->other), &bin_op_instruction->base);1217 bin_op_instruction->op_id, op1->other, op2->other), &bin_op_instruction->base);
8621218
863 return ira->old_irb.codegen->builtin_types.entry_bool;1219 return bool_type;
864}1220}
8651221
866static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) {1222static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) {
...@@ -925,12 +1281,109 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp...@@ -925,12 +1281,109 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp
925 zig_unreachable();1281 zig_unreachable();
926 }1282 }
9271283
1284 zig_panic("TODO interpret bin_op_cmp");
1285
928 ir_link_new(ir_build_bin_op(&ira->new_irb, bin_op_instruction->base.source_node,1286 ir_link_new(ir_build_bin_op(&ira->new_irb, bin_op_instruction->base.source_node,
929 op_id, op1->other, op2->other), &bin_op_instruction->base);1287 op_id, op1->other, op2->other), &bin_op_instruction->base);
9301288
931 return ira->old_irb.codegen->builtin_types.entry_bool;1289 return ira->old_irb.codegen->builtin_types.entry_bool;
932}1290}
9331291
1292static uint64_t max_unsigned_val(TypeTableEntry *type_entry) {
1293 assert(type_entry->id == TypeTableEntryIdInt);
1294 if (type_entry->data.integral.bit_count == 64) {
1295 return UINT64_MAX;
1296 } else if (type_entry->data.integral.bit_count == 32) {
1297 return UINT32_MAX;
1298 } else if (type_entry->data.integral.bit_count == 16) {
1299 return UINT16_MAX;
1300 } else if (type_entry->data.integral.bit_count == 8) {
1301 return UINT8_MAX;
1302 } else {
1303 zig_unreachable();
1304 }
1305}
1306
1307static int ir_eval_bignum(ConstExprValue *op1_val, ConstExprValue *op2_val,
1308 ConstExprValue *out_val, bool (*bignum_fn)(BigNum *, BigNum *, BigNum *),
1309 TypeTableEntry *type, bool wrapping_op)
1310{
1311 bool overflow = bignum_fn(&out_val->data.x_bignum, &op1_val->data.x_bignum, &op2_val->data.x_bignum);
1312 if (overflow) {
1313 return ErrorOverflow;
1314 }
1315
1316 if (type->id == TypeTableEntryIdInt && !bignum_fits_in_bits(&out_val->data.x_bignum,
1317 type->data.integral.bit_count, type->data.integral.is_signed))
1318 {
1319 if (wrapping_op) {
1320 if (type->data.integral.is_signed) {
1321 out_val->data.x_bignum.data.x_uint = max_unsigned_val(type) - out_val->data.x_bignum.data.x_uint + 1;
1322 out_val->data.x_bignum.is_negative = !out_val->data.x_bignum.is_negative;
1323 } else if (out_val->data.x_bignum.is_negative) {
1324 out_val->data.x_bignum.data.x_uint = max_unsigned_val(type) - out_val->data.x_bignum.data.x_uint + 1;
1325 out_val->data.x_bignum.is_negative = false;
1326 } else {
1327 bignum_truncate(&out_val->data.x_bignum, type->data.integral.bit_count);
1328 }
1329 } else {
1330 return ErrorOverflow;
1331 }
1332 }
1333
1334 out_val->ok = true;
1335 out_val->depends_on_compile_var = op1_val->depends_on_compile_var || op2_val->depends_on_compile_var;
1336 return 0;
1337}
1338
1339static int ir_eval_math_op(ConstExprValue *op1_val, TypeTableEntry *op1_type,
1340 IrBinOp op_id, ConstExprValue *op2_val, TypeTableEntry *op2_type, ConstExprValue *out_val)
1341{
1342 switch (op_id) {
1343 case IrBinOpInvalid:
1344 case IrBinOpBoolOr:
1345 case IrBinOpBoolAnd:
1346 case IrBinOpCmpEq:
1347 case IrBinOpCmpNotEq:
1348 case IrBinOpCmpLessThan:
1349 case IrBinOpCmpGreaterThan:
1350 case IrBinOpCmpLessOrEq:
1351 case IrBinOpCmpGreaterOrEq:
1352 case IrBinOpArrayCat:
1353 case IrBinOpArrayMult:
1354 zig_unreachable();
1355 case IrBinOpBinOr:
1356 return ir_eval_bignum(op1_val, op2_val, out_val, bignum_or, op1_type, false);
1357 case IrBinOpBinXor:
1358 return ir_eval_bignum(op1_val, op2_val, out_val, bignum_xor, op1_type, false);
1359 case IrBinOpBinAnd:
1360 return ir_eval_bignum(op1_val, op2_val, out_val, bignum_and, op1_type, false);
1361 case IrBinOpBitShiftLeft:
1362 return ir_eval_bignum(op1_val, op2_val, out_val, bignum_shl, op1_type, false);
1363 case IrBinOpBitShiftLeftWrap:
1364 return ir_eval_bignum(op1_val, op2_val, out_val, bignum_shl, op1_type, true);
1365 case IrBinOpBitShiftRight:
1366 return ir_eval_bignum(op1_val, op2_val, out_val, bignum_shr, op1_type, false);
1367 case IrBinOpAdd:
1368 return ir_eval_bignum(op1_val, op2_val, out_val, bignum_add, op1_type, false);
1369 case IrBinOpAddWrap:
1370 return ir_eval_bignum(op1_val, op2_val, out_val, bignum_add, op1_type, true);
1371 case IrBinOpSub:
1372 return ir_eval_bignum(op1_val, op2_val, out_val, bignum_sub, op1_type, false);
1373 case IrBinOpSubWrap:
1374 return ir_eval_bignum(op1_val, op2_val, out_val, bignum_sub, op1_type, true);
1375 case IrBinOpMult:
1376 return ir_eval_bignum(op1_val, op2_val, out_val, bignum_mul, op1_type, false);
1377 case IrBinOpMultWrap:
1378 return ir_eval_bignum(op1_val, op2_val, out_val, bignum_mul, op1_type, true);
1379 case IrBinOpDiv:
1380 return ir_eval_bignum(op1_val, op2_val, out_val, bignum_div, op1_type, false);
1381 case IrBinOpMod:
1382 return ir_eval_bignum(op1_val, op2_val, out_val, bignum_mod, op1_type, false);
1383 }
1384 zig_unreachable();
1385}
1386
934static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) {1387static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) {
935 IrInstruction *op1 = bin_op_instruction->op1;1388 IrInstruction *op1 = bin_op_instruction->op1;
936 IrInstruction *op2 = bin_op_instruction->op2;1389 IrInstruction *op2 = bin_op_instruction->op2;
...@@ -955,12 +1408,39 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp...@@ -955,12 +1408,39 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
955 // float1408 // float
956 } else {1409 } else {
957 AstNode *source_node = bin_op_instruction->base.source_node;1410 AstNode *source_node = bin_op_instruction->base.source_node;
958 add_node_error(ira->old_irb.codegen, source_node, buf_sprintf("invalid operands to binary expression: '%s' and '%s'",1411 add_node_error(ira->old_irb.codegen, source_node,
1412 buf_sprintf("invalid operands to binary expression: '%s' and '%s'",
959 buf_ptr(&op1->type_entry->name),1413 buf_ptr(&op1->type_entry->name),
960 buf_ptr(&op2->type_entry->name)));1414 buf_ptr(&op2->type_entry->name)));
961 return ira->old_irb.codegen->builtin_types.entry_invalid;1415 return ira->old_irb.codegen->builtin_types.entry_invalid;
962 }1416 }
9631417
1418 if (op1->static_value.ok && op2->static_value.ok) {
1419 ConstExprValue *op1_val = &op1->static_value;
1420 ConstExprValue *op2_val = &op2->static_value;
1421 ConstExprValue *out_val = &bin_op_instruction->base.static_value;
1422
1423 bin_op_instruction->base.other = &bin_op_instruction->base;
1424
1425 int err;
1426 if ((err = ir_eval_math_op(op1_val, resolved_type, op_id, op2_val, resolved_type, out_val))) {
1427 if (err == ErrorDivByZero) {
1428 add_node_error(ira->codegen, bin_op_instruction->base.source_node,
1429 buf_sprintf("division by zero is undefined"));
1430 return ira->codegen->builtin_types.entry_invalid;
1431 } else if (err == ErrorOverflow) {
1432 add_node_error(ira->codegen, bin_op_instruction->base.source_node,
1433 buf_sprintf("value cannot be represented in any integer type"));
1434 return ira->codegen->builtin_types.entry_invalid;
1435 }
1436 return ira->codegen->builtin_types.entry_invalid;
1437 }
1438
1439 ir_num_lit_fits_in_other_type(ira, &bin_op_instruction->base, resolved_type);
1440 return resolved_type;
1441
1442 }
1443
964 ir_link_new(ir_build_bin_op(&ira->new_irb, bin_op_instruction->base.source_node,1444 ir_link_new(ir_build_bin_op(&ira->new_irb, bin_op_instruction->base.source_node,
965 op_id, op1->other, op2->other), &bin_op_instruction->base);1445 op_id, op1->other, op2->other), &bin_op_instruction->base);
9661446
...@@ -1011,6 +1491,40 @@ static TypeTableEntry *ir_analyze_instruction_load_var(IrAnalyze *ira, IrInstruc...@@ -1011,6 +1491,40 @@ static TypeTableEntry *ir_analyze_instruction_load_var(IrAnalyze *ira, IrInstruc
1011 return load_var_instruction->var->type;1491 return load_var_instruction->var->type;
1012}1492}
10131493
1494static TypeTableEntry *ir_analyze_instruction_call(IrAnalyze *ira, IrInstructionCall *call_instruction) {
1495 IrInstruction *fn_ref = call_instruction->fn->other;
1496 if (fn_ref->type_entry->id == TypeTableEntryIdInvalid)
1497 return ira->codegen->builtin_types.entry_invalid;
1498
1499 if (fn_ref->static_value.ok) {
1500 if (fn_ref->type_entry->id == TypeTableEntryIdMetaType) {
1501 size_t actual_param_count = call_instruction->arg_count;
1502
1503 if (actual_param_count != 1) {
1504 add_node_error(ira->codegen, call_instruction->base.source_node,
1505 buf_sprintf("cast expression expects exactly one parameter"));
1506 return ira->codegen->builtin_types.entry_invalid;
1507 }
1508
1509 IrInstruction *arg = call_instruction->args[0];
1510 IrInstruction *cast_instruction = ir_analyze_cast(ira, &call_instruction->base, fn_ref, arg);
1511 if (cast_instruction == ira->codegen->invalid_instruction)
1512 return ira->codegen->builtin_types.entry_invalid;
1513
1514 ir_link_new(cast_instruction, &call_instruction->base);
1515 return cast_instruction->type_entry;
1516 } else {
1517 zig_panic("TODO analyze more fn call types");
1518 }
1519 } else {
1520 //ir_link_new(ir_build_call(&ira->new_irb, call_instruction->base.source_node,
1521 // call_instruction->fn, call_instruction->arg_count, call_instruction->args),
1522 // &call_instruction->base);
1523
1524 zig_panic("TODO analyze fn call");
1525 }
1526}
1527
1014static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {1528static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {
1015 switch (instruction->id) {1529 switch (instruction->id) {
1016 case IrInstructionIdInvalid:1530 case IrInstructionIdInvalid:
...@@ -1023,11 +1537,12 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi...@@ -1023,11 +1537,12 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
1023 return ir_analyze_instruction_bin_op(ira, (IrInstructionBinOp *)instruction);1537 return ir_analyze_instruction_bin_op(ira, (IrInstructionBinOp *)instruction);
1024 case IrInstructionIdLoadVar:1538 case IrInstructionIdLoadVar:
1025 return ir_analyze_instruction_load_var(ira, (IrInstructionLoadVar *)instruction);1539 return ir_analyze_instruction_load_var(ira, (IrInstructionLoadVar *)instruction);
1540 case IrInstructionIdCall:
1541 return ir_analyze_instruction_call(ira, (IrInstructionCall *)instruction);
1026 case IrInstructionIdCondBr:1542 case IrInstructionIdCondBr:
1027 case IrInstructionIdSwitchBr:1543 case IrInstructionIdSwitchBr:
1028 case IrInstructionIdPhi:1544 case IrInstructionIdPhi:
1029 case IrInstructionIdStoreVar:1545 case IrInstructionIdStoreVar:
1030 case IrInstructionIdCall:
1031 case IrInstructionIdBuiltinCall:1546 case IrInstructionIdBuiltinCall:
1032 case IrInstructionIdCast:1547 case IrInstructionIdCast:
1033 zig_panic("TODO analyze more instructions");1548 zig_panic("TODO analyze more instructions");
src/ir_print.cpp+29-4
...@@ -20,7 +20,7 @@ static void ir_print_prefix(IrPrint *irp, IrInstruction *instruction) {...@@ -20,7 +20,7 @@ static void ir_print_prefix(IrPrint *irp, IrInstruction *instruction) {
20static void ir_print_return(IrPrint *irp, IrInstructionReturn *return_instruction) {20static void ir_print_return(IrPrint *irp, IrInstructionReturn *return_instruction) {
21 ir_print_prefix(irp, &return_instruction->base);21 ir_print_prefix(irp, &return_instruction->base);
22 assert(return_instruction->value);22 assert(return_instruction->value);
23 fprintf(irp->f, "return #%zu;\n", return_instruction->value->debug_id);23 fprintf(irp->f, "return #%zu\n", return_instruction->value->debug_id);
24}24}
2525
26static void ir_print_const(IrPrint *irp, IrInstructionConst *const_instruction) {26static void ir_print_const(IrPrint *irp, IrInstructionConst *const_instruction) {
...@@ -43,8 +43,10 @@ static void ir_print_const(IrPrint *irp, IrInstructionConst *const_instruction)...@@ -43,8 +43,10 @@ static void ir_print_const(IrPrint *irp, IrInstructionConst *const_instruction)
43 fprintf(irp->f, "%s%llu\n", negative_str, bignum->data.x_uint);43 fprintf(irp->f, "%s%llu\n", negative_str, bignum->data.x_uint);
44 break;44 break;
45 }45 }
46 case TypeTableEntryIdVar:
47 case TypeTableEntryIdMetaType:46 case TypeTableEntryIdMetaType:
47 fprintf(irp->f, "%s\n", buf_ptr(&const_instruction->base.static_value.data.x_type->name));
48 break;
49 case TypeTableEntryIdVar:
48 case TypeTableEntryIdBool:50 case TypeTableEntryIdBool:
49 case TypeTableEntryIdUnreachable:51 case TypeTableEntryIdUnreachable:
50 case TypeTableEntryIdInt:52 case TypeTableEntryIdInt:
...@@ -139,6 +141,25 @@ static void ir_print_load_var(IrPrint *irp, IrInstructionLoadVar *load_var_instr...@@ -139,6 +141,25 @@ static void ir_print_load_var(IrPrint *irp, IrInstructionLoadVar *load_var_instr
139 buf_ptr(&load_var_instruction->var->name));141 buf_ptr(&load_var_instruction->var->name));
140}142}
141143
144static void ir_print_cast(IrPrint *irp, IrInstructionCast *cast_instruction) {
145 ir_print_prefix(irp, &cast_instruction->base);
146 fprintf(irp->f, "cast #%zu to #%zu\n",
147 cast_instruction->value->debug_id,
148 cast_instruction->dest_type->debug_id);
149}
150
151static void ir_print_call(IrPrint *irp, IrInstructionCall *call_instruction) {
152 ir_print_prefix(irp, &call_instruction->base);
153 fprintf(irp->f, "#%zu(", call_instruction->fn->debug_id);
154 for (size_t i = 0; i < call_instruction->arg_count; i += 1) {
155 IrInstruction *arg = call_instruction->args[i];
156 if (i != 0)
157 fprintf(irp->f, ", ");
158 fprintf(irp->f, "#%zu", arg->debug_id);
159 }
160 fprintf(irp->f, ")\n");
161}
162
142static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {163static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
143 switch (instruction->id) {164 switch (instruction->id) {
144 case IrInstructionIdInvalid:165 case IrInstructionIdInvalid:
...@@ -155,13 +176,17 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -155,13 +176,17 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
155 case IrInstructionIdLoadVar:176 case IrInstructionIdLoadVar:
156 ir_print_load_var(irp, (IrInstructionLoadVar *)instruction);177 ir_print_load_var(irp, (IrInstructionLoadVar *)instruction);
157 break;178 break;
179 case IrInstructionIdCast:
180 ir_print_cast(irp, (IrInstructionCast *)instruction);
181 break;
182 case IrInstructionIdCall:
183 ir_print_call(irp, (IrInstructionCall *)instruction);
184 break;
158 case IrInstructionIdCondBr:185 case IrInstructionIdCondBr:
159 case IrInstructionIdSwitchBr:186 case IrInstructionIdSwitchBr:
160 case IrInstructionIdPhi:187 case IrInstructionIdPhi:
161 case IrInstructionIdStoreVar:188 case IrInstructionIdStoreVar:
162 case IrInstructionIdCall:
163 case IrInstructionIdBuiltinCall:189 case IrInstructionIdBuiltinCall:
164 case IrInstructionIdCast:
165 zig_panic("TODO print more IR instructions");190 zig_panic("TODO print more IR instructions");
166 }191 }
167}192}