| ... | @@ -395,6 +395,22 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionBreakpoint *) { | ... | @@ -395,6 +395,22 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionBreakpoint *) { |
| 395 | return IrInstructionIdBreakpoint; | 395 | return IrInstructionIdBreakpoint; |
| 396 | } | 396 | } |
| 397 | | 397 | |
| | 398 | static constexpr IrInstructionId ir_instruction_id(IrInstructionReturnAddress *) { |
| | 399 | return IrInstructionIdReturnAddress; |
| | 400 | } |
| | 401 | |
| | 402 | static constexpr IrInstructionId ir_instruction_id(IrInstructionFrameAddress *) { |
| | 403 | return IrInstructionIdFrameAddress; |
| | 404 | } |
| | 405 | |
| | 406 | static constexpr IrInstructionId ir_instruction_id(IrInstructionAlignOf *) { |
| | 407 | return IrInstructionIdAlignOf; |
| | 408 | } |
| | 409 | |
| | 410 | static constexpr IrInstructionId ir_instruction_id(IrInstructionOverflowOp *) { |
| | 411 | return IrInstructionIdOverflowOp; |
| | 412 | } |
| | 413 | |
| 398 | template<typename T> | 414 | template<typename T> |
| 399 | static T *ir_create_instruction(IrExecutable *exec, Scope *scope, AstNode *source_node) { | 415 | static T *ir_create_instruction(IrExecutable *exec, Scope *scope, AstNode *source_node) { |
| 400 | T *special_instruction = allocate<T>(1); | 416 | T *special_instruction = allocate<T>(1); |
| ... | @@ -1632,6 +1648,67 @@ static IrInstruction *ir_build_breakpoint_from(IrBuilder *irb, IrInstruction *ol | ... | @@ -1632,6 +1648,67 @@ static IrInstruction *ir_build_breakpoint_from(IrBuilder *irb, IrInstruction *ol |
| 1632 | return new_instruction; | 1648 | return new_instruction; |
| 1633 | } | 1649 | } |
| 1634 | | 1650 | |
| | 1651 | static IrInstruction *ir_build_return_address(IrBuilder *irb, Scope *scope, AstNode *source_node) { |
| | 1652 | IrInstructionReturnAddress *instruction = ir_build_instruction<IrInstructionReturnAddress>(irb, scope, source_node); |
| | 1653 | return &instruction->base; |
| | 1654 | } |
| | 1655 | |
| | 1656 | static IrInstruction *ir_build_return_address_from(IrBuilder *irb, IrInstruction *old_instruction) { |
| | 1657 | IrInstruction *new_instruction = ir_build_return_address(irb, old_instruction->scope, old_instruction->source_node); |
| | 1658 | ir_link_new_instruction(new_instruction, old_instruction); |
| | 1659 | return new_instruction; |
| | 1660 | } |
| | 1661 | |
| | 1662 | static IrInstruction *ir_build_frame_address(IrBuilder *irb, Scope *scope, AstNode *source_node) { |
| | 1663 | IrInstructionFrameAddress *instruction = ir_build_instruction<IrInstructionFrameAddress>(irb, scope, source_node); |
| | 1664 | return &instruction->base; |
| | 1665 | } |
| | 1666 | |
| | 1667 | static IrInstruction *ir_build_frame_address_from(IrBuilder *irb, IrInstruction *old_instruction) { |
| | 1668 | IrInstruction *new_instruction = ir_build_frame_address(irb, old_instruction->scope, old_instruction->source_node); |
| | 1669 | ir_link_new_instruction(new_instruction, old_instruction); |
| | 1670 | return new_instruction; |
| | 1671 | } |
| | 1672 | |
| | 1673 | static IrInstruction *ir_build_overflow_op(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| | 1674 | IrOverflowOp op, IrInstruction *type_value, IrInstruction *op1, IrInstruction *op2, |
| | 1675 | IrInstruction *result_ptr, TypeTableEntry *result_ptr_type) |
| | 1676 | { |
| | 1677 | IrInstructionOverflowOp *instruction = ir_build_instruction<IrInstructionOverflowOp>(irb, scope, source_node); |
| | 1678 | instruction->op = op; |
| | 1679 | instruction->type_value = type_value; |
| | 1680 | instruction->op1 = op1; |
| | 1681 | instruction->op2 = op2; |
| | 1682 | instruction->result_ptr = result_ptr; |
| | 1683 | instruction->result_ptr_type = result_ptr_type; |
| | 1684 | |
| | 1685 | ir_ref_instruction(type_value); |
| | 1686 | ir_ref_instruction(op1); |
| | 1687 | ir_ref_instruction(op2); |
| | 1688 | ir_ref_instruction(result_ptr); |
| | 1689 | |
| | 1690 | return &instruction->base; |
| | 1691 | } |
| | 1692 | |
| | 1693 | static IrInstruction *ir_build_overflow_op_from(IrBuilder *irb, IrInstruction *old_instruction, |
| | 1694 | IrOverflowOp op, IrInstruction *type_value, IrInstruction *op1, IrInstruction *op2, |
| | 1695 | IrInstruction *result_ptr, TypeTableEntry *result_ptr_type) |
| | 1696 | { |
| | 1697 | IrInstruction *new_instruction = ir_build_overflow_op(irb, old_instruction->scope, old_instruction->source_node, |
| | 1698 | op, type_value, op1, op2, result_ptr, result_ptr_type); |
| | 1699 | ir_link_new_instruction(new_instruction, old_instruction); |
| | 1700 | return new_instruction; |
| | 1701 | } |
| | 1702 | |
| | 1703 | static IrInstruction *ir_build_alignof(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type_value) { |
| | 1704 | IrInstructionAlignOf *instruction = ir_build_instruction<IrInstructionAlignOf>(irb, scope, source_node); |
| | 1705 | instruction->type_value = type_value; |
| | 1706 | |
| | 1707 | ir_ref_instruction(type_value); |
| | 1708 | |
| | 1709 | return &instruction->base; |
| | 1710 | } |
| | 1711 | |
| 1635 | static void ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, | 1712 | static void ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, |
| 1636 | bool gen_error_defers, bool gen_maybe_defers) | 1713 | bool gen_error_defers, bool gen_maybe_defers) |
| 1637 | { | 1714 | { |
| ... | @@ -2142,6 +2219,34 @@ static IrInstruction *ir_gen_field_access(IrBuilder *irb, Scope *scope, AstNode | ... | @@ -2142,6 +2219,34 @@ static IrInstruction *ir_gen_field_access(IrBuilder *irb, Scope *scope, AstNode |
| 2142 | return ir_build_load_ptr(irb, scope, node, ptr_instruction); | 2219 | return ir_build_load_ptr(irb, scope, node, ptr_instruction); |
| 2143 | } | 2220 | } |
| 2144 | | 2221 | |
| | 2222 | static IrInstruction *ir_gen_overflow_op(IrBuilder *irb, Scope *scope, AstNode *node, IrOverflowOp op) { |
| | 2223 | assert(node->type == NodeTypeFnCallExpr); |
| | 2224 | |
| | 2225 | AstNode *type_node = node->data.fn_call_expr.params.at(0); |
| | 2226 | AstNode *op1_node = node->data.fn_call_expr.params.at(1); |
| | 2227 | AstNode *op2_node = node->data.fn_call_expr.params.at(2); |
| | 2228 | AstNode *result_ptr_node = node->data.fn_call_expr.params.at(3); |
| | 2229 | |
| | 2230 | |
| | 2231 | IrInstruction *type_value = ir_gen_node(irb, type_node, scope); |
| | 2232 | if (type_value == irb->codegen->invalid_instruction) |
| | 2233 | return irb->codegen->invalid_instruction; |
| | 2234 | |
| | 2235 | IrInstruction *op1 = ir_gen_node(irb, op1_node, scope); |
| | 2236 | if (op1 == irb->codegen->invalid_instruction) |
| | 2237 | return irb->codegen->invalid_instruction; |
| | 2238 | |
| | 2239 | IrInstruction *op2 = ir_gen_node(irb, op2_node, scope); |
| | 2240 | if (op2 == irb->codegen->invalid_instruction) |
| | 2241 | return irb->codegen->invalid_instruction; |
| | 2242 | |
| | 2243 | IrInstruction *result_ptr = ir_gen_node(irb, result_ptr_node, scope); |
| | 2244 | if (result_ptr == irb->codegen->invalid_instruction) |
| | 2245 | return irb->codegen->invalid_instruction; |
| | 2246 | |
| | 2247 | return ir_build_overflow_op(irb, scope, node, op, type_value, op1, op2, result_ptr, nullptr); |
| | 2248 | } |
| | 2249 | |
| 2145 | static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNode *node) { | 2250 | static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNode *node) { |
| 2146 | assert(node->type == NodeTypeFnCallExpr); | 2251 | assert(node->type == NodeTypeFnCallExpr); |
| 2147 | | 2252 | |
| ... | @@ -2522,14 +2627,27 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo | ... | @@ -2522,14 +2627,27 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo |
| 2522 | } | 2627 | } |
| 2523 | case BuiltinFnIdBreakpoint: | 2628 | case BuiltinFnIdBreakpoint: |
| 2524 | return ir_build_breakpoint(irb, scope, node); | 2629 | return ir_build_breakpoint(irb, scope, node); |
| | 2630 | case BuiltinFnIdReturnAddress: |
| | 2631 | return ir_build_return_address(irb, scope, node); |
| | 2632 | case BuiltinFnIdFrameAddress: |
| | 2633 | return ir_build_frame_address(irb, scope, node); |
| 2525 | case BuiltinFnIdAlignof: | 2634 | case BuiltinFnIdAlignof: |
| | 2635 | { |
| | 2636 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); |
| | 2637 | IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); |
| | 2638 | if (arg0_value == irb->codegen->invalid_instruction) |
| | 2639 | return arg0_value; |
| | 2640 | |
| | 2641 | return ir_build_alignof(irb, scope, node, arg0_value); |
| | 2642 | } |
| 2526 | case BuiltinFnIdAddWithOverflow: | 2643 | case BuiltinFnIdAddWithOverflow: |
| | 2644 | return ir_gen_overflow_op(irb, scope, node, IrOverflowOpAdd); |
| 2527 | case BuiltinFnIdSubWithOverflow: | 2645 | case BuiltinFnIdSubWithOverflow: |
| | 2646 | return ir_gen_overflow_op(irb, scope, node, IrOverflowOpSub); |
| 2528 | case BuiltinFnIdMulWithOverflow: | 2647 | case BuiltinFnIdMulWithOverflow: |
| | 2648 | return ir_gen_overflow_op(irb, scope, node, IrOverflowOpMul); |
| 2529 | case BuiltinFnIdShlWithOverflow: | 2649 | case BuiltinFnIdShlWithOverflow: |
| 2530 | case BuiltinFnIdReturnAddress: | 2650 | return ir_gen_overflow_op(irb, scope, node, IrOverflowOpShl); |
| 2531 | case BuiltinFnIdFrameAddress: | | |
| 2532 | zig_panic("TODO IR gen more builtin functions"); | | |
| 2533 | } | 2651 | } |
| 2534 | zig_unreachable(); | 2652 | zig_unreachable(); |
| 2535 | } | 2653 | } |
| ... | @@ -2749,10 +2867,6 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod | ... | @@ -2749,10 +2867,6 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod |
| 2749 | type_instruction = nullptr; | 2867 | type_instruction = nullptr; |
| 2750 | } | 2868 | } |
| 2751 | | 2869 | |
| 2752 | IrInstruction *init_value = ir_gen_node(irb, variable_declaration->expr, scope); | | |
| 2753 | if (init_value == irb->codegen->invalid_instruction) | | |
| 2754 | return init_value; | | |
| 2755 | | | |
| 2756 | bool is_shadowable = false; | 2870 | bool is_shadowable = false; |
| 2757 | bool is_const = variable_declaration->is_const; | 2871 | bool is_const = variable_declaration->is_const; |
| 2758 | bool is_extern = variable_declaration->is_extern; | 2872 | bool is_extern = variable_declaration->is_extern; |
| ... | @@ -2768,6 +2882,10 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod | ... | @@ -2768,6 +2882,10 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod |
| 2768 | return irb->codegen->invalid_instruction; | 2882 | return irb->codegen->invalid_instruction; |
| 2769 | } | 2883 | } |
| 2770 | | 2884 | |
| | 2885 | IrInstruction *init_value = ir_gen_node(irb, variable_declaration->expr, scope); |
| | 2886 | if (init_value == irb->codegen->invalid_instruction) |
| | 2887 | return init_value; |
| | 2888 | |
| 2771 | return ir_build_var_decl(irb, scope, node, var, type_instruction, init_value); | 2889 | return ir_build_var_decl(irb, scope, node, var, type_instruction, init_value); |
| 2772 | } | 2890 | } |
| 2773 | | 2891 | |
| ... | @@ -4057,9 +4175,9 @@ static TypeTableEntry *ir_analyze_void(IrAnalyze *ira, IrInstruction *instructio | ... | @@ -4057,9 +4175,9 @@ static TypeTableEntry *ir_analyze_void(IrAnalyze *ira, IrInstruction *instructio |
| 4057 | | 4175 | |
| 4058 | static TypeTableEntry *ir_analyze_const_ptr(IrAnalyze *ira, IrInstruction *instruction, | 4176 | static TypeTableEntry *ir_analyze_const_ptr(IrAnalyze *ira, IrInstruction *instruction, |
| 4059 | ConstExprValue *pointee, TypeTableEntry *pointee_type, bool depends_on_compile_var, | 4177 | ConstExprValue *pointee, TypeTableEntry *pointee_type, bool depends_on_compile_var, |
| 4060 | ConstPtrSpecial special) | 4178 | ConstPtrSpecial special, bool ptr_is_const) |
| 4061 | { | 4179 | { |
| 4062 | TypeTableEntry *ptr_type = get_pointer_to_type(ira->codegen, pointee_type, true); | 4180 | TypeTableEntry *ptr_type = get_pointer_to_type(ira->codegen, pointee_type, ptr_is_const); |
| 4063 | ConstExprValue *const_val = ir_build_const_from(ira, instruction, | 4181 | ConstExprValue *const_val = ir_build_const_from(ira, instruction, |
| 4064 | depends_on_compile_var || pointee->depends_on_compile_var); | 4182 | depends_on_compile_var || pointee->depends_on_compile_var); |
| 4065 | const_val->data.x_ptr.base_ptr = pointee; | 4183 | const_val->data.x_ptr.base_ptr = pointee; |
| ... | @@ -4086,7 +4204,7 @@ static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value) { | ... | @@ -4086,7 +4204,7 @@ static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value) { |
| 4086 | | 4204 | |
| 4087 | IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, | 4205 | IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, |
| 4088 | TypeTableEntry *expected_type, size_t *backward_branch_count, size_t backward_branch_quota, | 4206 | TypeTableEntry *expected_type, size_t *backward_branch_count, size_t backward_branch_quota, |
| 4089 | FnTableEntry *fn_entry, Buf *c_import_buf) | 4207 | FnTableEntry *fn_entry, Buf *c_import_buf, AstNode *source_node) |
| 4090 | { | 4208 | { |
| 4091 | IrExecutable ir_executable = {0}; | 4209 | IrExecutable ir_executable = {0}; |
| 4092 | ir_executable.is_inline = true; | 4210 | ir_executable.is_inline = true; |
| ... | @@ -4122,7 +4240,7 @@ IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node | ... | @@ -4122,7 +4240,7 @@ IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node |
| 4122 | | 4240 | |
| 4123 | IrInstruction *result = ir_exec_const_result(&analyzed_executable); | 4241 | IrInstruction *result = ir_exec_const_result(&analyzed_executable); |
| 4124 | if (!result) { | 4242 | if (!result) { |
| 4125 | add_node_error(codegen, node, buf_sprintf("unable to evaluate constant expression")); | 4243 | add_node_error(codegen, source_node, buf_sprintf("unable to evaluate constant expression")); |
| 4126 | return codegen->invalid_instruction; | 4244 | return codegen->invalid_instruction; |
| 4127 | } | 4245 | } |
| 4128 | | 4246 | |
| ... | @@ -4499,7 +4617,9 @@ static TypeTableEntry *ir_analyze_ref(IrAnalyze *ira, IrInstruction *source_inst | ... | @@ -4499,7 +4617,9 @@ static TypeTableEntry *ir_analyze_ref(IrAnalyze *ira, IrInstruction *source_inst |
| 4499 | ConstExprValue *val = ir_resolve_const(ira, value); | 4617 | ConstExprValue *val = ir_resolve_const(ira, value); |
| 4500 | if (!val) | 4618 | if (!val) |
| 4501 | return ira->codegen->builtin_types.entry_invalid; | 4619 | return ira->codegen->builtin_types.entry_invalid; |
| 4502 | return ir_analyze_const_ptr(ira, source_instruction, val, value->type_entry, false, ConstPtrSpecialNone); | 4620 | bool ptr_is_const = true; |
| | 4621 | return ir_analyze_const_ptr(ira, source_instruction, val, value->type_entry, |
| | 4622 | false, ConstPtrSpecialNone, ptr_is_const); |
| 4503 | } | 4623 | } |
| 4504 | | 4624 | |
| 4505 | TypeTableEntry *ptr_type = get_pointer_to_type(ira->codegen, value->type_entry, true); | 4625 | TypeTableEntry *ptr_type = get_pointer_to_type(ira->codegen, value->type_entry, true); |
| ... | @@ -5230,11 +5350,16 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc | ... | @@ -5230,11 +5350,16 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc |
| 5230 | var->type = result_type; | 5350 | var->type = result_type; |
| 5231 | assert(var->type); | 5351 | assert(var->type); |
| 5232 | | 5352 | |
| 5233 | if (casted_init_value->static_value.special == ConstValSpecialStatic) { | 5353 | if (casted_init_value->static_value.special != ConstValSpecialRuntime) { |
| 5234 | if (var->mem_slot_index != SIZE_MAX) { | 5354 | if (var->mem_slot_index != SIZE_MAX) { |
| 5235 | assert(var->mem_slot_index < ira->exec_context.mem_slot_count); | 5355 | assert(var->mem_slot_index < ira->exec_context.mem_slot_count); |
| 5236 | ConstExprValue *mem_slot = &ira->exec_context.mem_slot_list[var->mem_slot_index]; | 5356 | ConstExprValue *mem_slot = &ira->exec_context.mem_slot_list[var->mem_slot_index]; |
| 5237 | *mem_slot = casted_init_value->static_value; | 5357 | *mem_slot = casted_init_value->static_value; |
| | 5358 | |
| | 5359 | if (var->is_inline) { |
| | 5360 | ir_build_const_from(ira, &decl_var_instruction->base, false); |
| | 5361 | return ira->codegen->builtin_types.entry_void; |
| | 5362 | } |
| 5238 | } | 5363 | } |
| 5239 | } else if (var->is_inline) { | 5364 | } else if (var->is_inline) { |
| 5240 | ir_add_error(ira, &decl_var_instruction->base, | 5365 | ir_add_error(ira, &decl_var_instruction->base, |
| ... | @@ -5403,7 +5528,8 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal | ... | @@ -5403,7 +5528,8 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal |
| 5403 | // Analyze the fn body block like any other constant expression. | 5528 | // Analyze the fn body block like any other constant expression. |
| 5404 | AstNode *body_node = fn_entry->fn_def_node->data.fn_def.body; | 5529 | AstNode *body_node = fn_entry->fn_def_node->data.fn_def.body; |
| 5405 | IrInstruction *result = ir_eval_const_value(ira->codegen, exec_scope, body_node, return_type, | 5530 | IrInstruction *result = ir_eval_const_value(ira->codegen, exec_scope, body_node, return_type, |
| 5406 | ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, fn_entry, nullptr); | 5531 | ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, fn_entry, |
| | 5532 | nullptr, call_instruction->base.source_node); |
| 5407 | if (result->type_entry->id == TypeTableEntryIdInvalid) | 5533 | if (result->type_entry->id == TypeTableEntryIdInvalid) |
| 5408 | return ira->codegen->builtin_types.entry_invalid; | 5534 | return ira->codegen->builtin_types.entry_invalid; |
| 5409 | | 5535 | |
| ... | @@ -6055,7 +6181,7 @@ static TypeTableEntry *ir_analyze_var_ptr(IrAnalyze *ira, IrInstruction *instruc | ... | @@ -6055,7 +6181,7 @@ static TypeTableEntry *ir_analyze_var_ptr(IrAnalyze *ira, IrInstruction *instruc |
| 6055 | | 6181 | |
| 6056 | if (mem_slot && mem_slot->special != ConstValSpecialRuntime) { | 6182 | if (mem_slot && mem_slot->special != ConstValSpecialRuntime) { |
| 6057 | ConstPtrSpecial ptr_special = var->is_inline ? ConstPtrSpecialInline : ConstPtrSpecialNone; | 6183 | ConstPtrSpecial ptr_special = var->is_inline ? ConstPtrSpecialInline : ConstPtrSpecialNone; |
| 6058 | return ir_analyze_const_ptr(ira, instruction, mem_slot, var->type, false, ptr_special); | 6184 | return ir_analyze_const_ptr(ira, instruction, mem_slot, var->type, false, ptr_special, var->src_is_const); |
| 6059 | } else { | 6185 | } else { |
| 6060 | ir_build_var_ptr_from(&ira->new_irb, instruction, var); | 6186 | ir_build_var_ptr_from(&ira->new_irb, instruction, var); |
| 6061 | return get_pointer_to_type(ira->codegen, var->type, false); | 6187 | return get_pointer_to_type(ira->codegen, var->type, false); |
| ... | @@ -6270,7 +6396,9 @@ static TypeTableEntry *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source | ... | @@ -6270,7 +6396,9 @@ static TypeTableEntry *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source |
| 6270 | const_val->special = ConstValSpecialStatic; | 6396 | const_val->special = ConstValSpecialStatic; |
| 6271 | const_val->data.x_fn = fn_entry; | 6397 | const_val->data.x_fn = fn_entry; |
| 6272 | | 6398 | |
| 6273 | return ir_analyze_const_ptr(ira, source_instruction, const_val, fn_entry->type_entry, depends_on_compile_var, ConstPtrSpecialNone); | 6399 | bool ptr_is_const = true; |
| | 6400 | return ir_analyze_const_ptr(ira, source_instruction, const_val, fn_entry->type_entry, |
| | 6401 | depends_on_compile_var, ConstPtrSpecialNone, ptr_is_const); |
| 6274 | } | 6402 | } |
| 6275 | case TldIdContainer: | 6403 | case TldIdContainer: |
| 6276 | { | 6404 | { |
| ... | @@ -6283,7 +6411,9 @@ static TypeTableEntry *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source | ... | @@ -6283,7 +6411,9 @@ static TypeTableEntry *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source |
| 6283 | const_val->special = ConstValSpecialStatic; | 6411 | const_val->special = ConstValSpecialStatic; |
| 6284 | const_val->data.x_type = tld_container->type_entry; | 6412 | const_val->data.x_type = tld_container->type_entry; |
| 6285 | | 6413 | |
| 6286 | return ir_analyze_const_ptr(ira, source_instruction, const_val, tld_container->type_entry, depends_on_compile_var, ConstPtrSpecialNone); | 6414 | bool ptr_is_const = true; |
| | 6415 | return ir_analyze_const_ptr(ira, source_instruction, const_val, tld_container->type_entry, |
| | 6416 | depends_on_compile_var, ConstPtrSpecialNone, ptr_is_const); |
| 6287 | } | 6417 | } |
| 6288 | case TldIdTypeDef: | 6418 | case TldIdTypeDef: |
| 6289 | { | 6419 | { |
| ... | @@ -6296,7 +6426,9 @@ static TypeTableEntry *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source | ... | @@ -6296,7 +6426,9 @@ static TypeTableEntry *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source |
| 6296 | const_val->special = ConstValSpecialStatic; | 6426 | const_val->special = ConstValSpecialStatic; |
| 6297 | const_val->data.x_type = tld_typedef->type_entry; | 6427 | const_val->data.x_type = tld_typedef->type_entry; |
| 6298 | | 6428 | |
| 6299 | return ir_analyze_const_ptr(ira, source_instruction, const_val, tld_typedef->type_entry, depends_on_compile_var, ConstPtrSpecialNone); | 6429 | bool ptr_is_const = true; |
| | 6430 | return ir_analyze_const_ptr(ira, source_instruction, const_val, tld_typedef->type_entry, |
| | 6431 | depends_on_compile_var, ConstPtrSpecialNone, ptr_is_const); |
| 6300 | } | 6432 | } |
| 6301 | } | 6433 | } |
| 6302 | zig_unreachable(); | 6434 | zig_unreachable(); |
| ... | @@ -6332,7 +6464,9 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru | ... | @@ -6332,7 +6464,9 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru |
| 6332 | bignum_init_unsigned(&len_val->data.x_bignum, container_type->data.array.len); | 6464 | bignum_init_unsigned(&len_val->data.x_bignum, container_type->data.array.len); |
| 6333 | | 6465 | |
| 6334 | TypeTableEntry *usize = ira->codegen->builtin_types.entry_usize; | 6466 | TypeTableEntry *usize = ira->codegen->builtin_types.entry_usize; |
| 6335 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, len_val, usize, false, ConstPtrSpecialNone); | 6467 | bool ptr_is_const = true; |
| | 6468 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, len_val, |
| | 6469 | usize, false, ConstPtrSpecialNone, ptr_is_const); |
| 6336 | } else { | 6470 | } else { |
| 6337 | add_node_error(ira->codegen, source_node, | 6471 | add_node_error(ira->codegen, source_node, |
| 6338 | buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name), | 6472 | buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name), |
| ... | @@ -6363,8 +6497,10 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru | ... | @@ -6363,8 +6497,10 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru |
| 6363 | TypeEnumField *field = find_enum_type_field(child_type, field_name); | 6497 | TypeEnumField *field = find_enum_type_field(child_type, field_name); |
| 6364 | if (field) { | 6498 | if (field) { |
| 6365 | if (field->type_entry->id == TypeTableEntryIdVoid) { | 6499 | if (field->type_entry->id == TypeTableEntryIdVoid) { |
| 6366 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, create_const_enum_tag(field->value), | 6500 | bool ptr_is_const = true; |
| 6367 | child_type, depends_on_compile_var, ConstPtrSpecialNone); | 6501 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, |
| | 6502 | create_const_enum_tag(field->value), child_type, depends_on_compile_var, |
| | 6503 | ConstPtrSpecialNone, ptr_is_const); |
| 6368 | } else { | 6504 | } else { |
| 6369 | zig_panic("TODO enum tag type"); | 6505 | zig_panic("TODO enum tag type"); |
| 6370 | } | 6506 | } |
| ... | @@ -6387,8 +6523,9 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru | ... | @@ -6387,8 +6523,9 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru |
| 6387 | const_val->special = ConstValSpecialStatic; | 6523 | const_val->special = ConstValSpecialStatic; |
| 6388 | const_val->data.x_pure_err = err_table_entry->value; | 6524 | const_val->data.x_pure_err = err_table_entry->value; |
| 6389 | | 6525 | |
| | 6526 | bool ptr_is_const = true; |
| 6390 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, const_val, | 6527 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, const_val, |
| 6391 | child_type, depends_on_compile_var, ConstPtrSpecialNone); | 6528 | child_type, depends_on_compile_var, ConstPtrSpecialNone, ptr_is_const); |
| 6392 | } | 6529 | } |
| 6393 | | 6530 | |
| 6394 | ir_add_error(ira, &field_ptr_instruction->base, | 6531 | ir_add_error(ira, &field_ptr_instruction->base, |
| ... | @@ -6396,13 +6533,17 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru | ... | @@ -6396,13 +6533,17 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru |
| 6396 | return ira->codegen->builtin_types.entry_invalid; | 6533 | return ira->codegen->builtin_types.entry_invalid; |
| 6397 | } else if (child_type->id == TypeTableEntryIdInt) { | 6534 | } else if (child_type->id == TypeTableEntryIdInt) { |
| 6398 | if (buf_eql_str(field_name, "bit_count")) { | 6535 | if (buf_eql_str(field_name, "bit_count")) { |
| | 6536 | bool ptr_is_const = true; |
| 6399 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, | 6537 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, |
| 6400 | create_const_unsigned_negative(child_type->data.integral.bit_count, false), | 6538 | create_const_unsigned_negative(child_type->data.integral.bit_count, false), |
| 6401 | ira->codegen->builtin_types.entry_num_lit_int, depends_on_compile_var, ConstPtrSpecialNone); | 6539 | ira->codegen->builtin_types.entry_num_lit_int, depends_on_compile_var, |
| | 6540 | ConstPtrSpecialNone, ptr_is_const); |
| 6402 | } else if (buf_eql_str(field_name, "is_signed")) { | 6541 | } else if (buf_eql_str(field_name, "is_signed")) { |
| | 6542 | bool ptr_is_const = true; |
| 6403 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, | 6543 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, |
| 6404 | create_const_bool(child_type->data.integral.is_signed), | 6544 | create_const_bool(child_type->data.integral.is_signed), |
| 6405 | ira->codegen->builtin_types.entry_bool, depends_on_compile_var, ConstPtrSpecialNone); | 6545 | ira->codegen->builtin_types.entry_bool, depends_on_compile_var, |
| | 6546 | ConstPtrSpecialNone, ptr_is_const); |
| 6406 | } else { | 6547 | } else { |
| 6407 | ir_add_error(ira, &field_ptr_instruction->base, | 6548 | ir_add_error(ira, &field_ptr_instruction->base, |
| 6408 | buf_sprintf("type '%s' has no member called '%s'", | 6549 | buf_sprintf("type '%s' has no member called '%s'", |
| ... | @@ -7713,7 +7854,8 @@ static TypeTableEntry *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruc | ... | @@ -7713,7 +7854,8 @@ static TypeTableEntry *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruc |
| 7713 | // Execute the C import block like an inline function | 7854 | // Execute the C import block like an inline function |
| 7714 | TypeTableEntry *void_type = ira->codegen->builtin_types.entry_void; | 7855 | TypeTableEntry *void_type = ira->codegen->builtin_types.entry_void; |
| 7715 | IrInstruction *result = ir_eval_const_value(ira->codegen, &cimport_scope->base, block_node, void_type, | 7856 | IrInstruction *result = ir_eval_const_value(ira->codegen, &cimport_scope->base, block_node, void_type, |
| 7716 | ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, nullptr, &cimport_scope->buf); | 7857 | ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, nullptr, |
| | 7858 | &cimport_scope->buf, block_node); |
| 7717 | if (result->type_entry->id == TypeTableEntryIdInvalid) | 7859 | if (result->type_entry->id == TypeTableEntryIdInvalid) |
| 7718 | return ira->codegen->builtin_types.entry_invalid; | 7860 | return ira->codegen->builtin_types.entry_invalid; |
| 7719 | | 7861 | |
| ... | @@ -8492,6 +8634,125 @@ static TypeTableEntry *ir_analyze_instruction_breakpoint(IrAnalyze *ira, IrInstr | ... | @@ -8492,6 +8634,125 @@ static TypeTableEntry *ir_analyze_instruction_breakpoint(IrAnalyze *ira, IrInstr |
| 8492 | return ira->codegen->builtin_types.entry_void; | 8634 | return ira->codegen->builtin_types.entry_void; |
| 8493 | } | 8635 | } |
| 8494 | | 8636 | |
| | 8637 | static TypeTableEntry *ir_analyze_instruction_return_address(IrAnalyze *ira, IrInstructionReturnAddress *instruction) { |
| | 8638 | ir_build_return_address_from(&ira->new_irb, &instruction->base); |
| | 8639 | |
| | 8640 | TypeTableEntry *u8 = ira->codegen->builtin_types.entry_u8; |
| | 8641 | TypeTableEntry *u8_ptr_const = get_pointer_to_type(ira->codegen, u8, true); |
| | 8642 | return u8_ptr_const; |
| | 8643 | } |
| | 8644 | |
| | 8645 | static TypeTableEntry *ir_analyze_instruction_frame_address(IrAnalyze *ira, IrInstructionFrameAddress *instruction) { |
| | 8646 | ir_build_frame_address_from(&ira->new_irb, &instruction->base); |
| | 8647 | |
| | 8648 | TypeTableEntry *u8 = ira->codegen->builtin_types.entry_u8; |
| | 8649 | TypeTableEntry *u8_ptr_const = get_pointer_to_type(ira->codegen, u8, true); |
| | 8650 | return u8_ptr_const; |
| | 8651 | } |
| | 8652 | |
| | 8653 | static TypeTableEntry *ir_analyze_instruction_alignof(IrAnalyze *ira, IrInstructionAlignOf *instruction) { |
| | 8654 | IrInstruction *type_value = instruction->type_value->other; |
| | 8655 | if (type_value->type_entry->id == TypeTableEntryIdInvalid) |
| | 8656 | return ira->codegen->builtin_types.entry_invalid; |
| | 8657 | TypeTableEntry *type_entry = ir_resolve_type(ira, type_value); |
| | 8658 | |
| | 8659 | if (type_entry->id == TypeTableEntryIdInvalid) { |
| | 8660 | return ira->codegen->builtin_types.entry_invalid; |
| | 8661 | } else if (type_entry->id == TypeTableEntryIdUnreachable) { |
| | 8662 | add_node_error(ira->codegen, first_executing_node(instruction->type_value->source_node), |
| | 8663 | buf_sprintf("no align available for type '%s'", buf_ptr(&type_entry->name))); |
| | 8664 | return ira->codegen->builtin_types.entry_invalid; |
| | 8665 | } else { |
| | 8666 | uint64_t align_in_bytes = LLVMABISizeOfType(ira->codegen->target_data_ref, type_entry->type_ref); |
| | 8667 | bool depends_on_compile_var = type_value->static_value.depends_on_compile_var; |
| | 8668 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base, depends_on_compile_var); |
| | 8669 | bignum_init_unsigned(&out_val->data.x_bignum, align_in_bytes); |
| | 8670 | return ira->codegen->builtin_types.entry_num_lit_int; |
| | 8671 | } |
| | 8672 | } |
| | 8673 | |
| | 8674 | static TypeTableEntry *ir_analyze_instruction_overflow_op(IrAnalyze *ira, IrInstructionOverflowOp *instruction) { |
| | 8675 | IrInstruction *type_value = instruction->type_value->other; |
| | 8676 | if (type_value->type_entry->id == TypeTableEntryIdInvalid) |
| | 8677 | return ira->codegen->builtin_types.entry_invalid; |
| | 8678 | TypeTableEntry *dest_type = ir_resolve_type(ira, type_value); |
| | 8679 | TypeTableEntry *canon_type = get_underlying_type(dest_type); |
| | 8680 | if (canon_type->id == TypeTableEntryIdInvalid) |
| | 8681 | return ira->codegen->builtin_types.entry_invalid; |
| | 8682 | |
| | 8683 | if (canon_type->id != TypeTableEntryIdInt) { |
| | 8684 | ir_add_error(ira, type_value, |
| | 8685 | buf_sprintf("expected integer type, found '%s'", buf_ptr(&dest_type->name))); |
| | 8686 | // TODO if this is a typedecl, add error note showing the declaration of the type decl |
| | 8687 | return ira->codegen->builtin_types.entry_invalid; |
| | 8688 | } |
| | 8689 | |
| | 8690 | IrInstruction *op1 = instruction->op1->other; |
| | 8691 | if (op1->type_entry->id == TypeTableEntryIdInvalid) |
| | 8692 | return ira->codegen->builtin_types.entry_invalid; |
| | 8693 | |
| | 8694 | IrInstruction *casted_op1 = ir_implicit_cast(ira, op1, dest_type); |
| | 8695 | if (casted_op1->type_entry->id == TypeTableEntryIdInvalid) |
| | 8696 | return ira->codegen->builtin_types.entry_invalid; |
| | 8697 | |
| | 8698 | IrInstruction *op2 = instruction->op2->other; |
| | 8699 | if (op2->type_entry->id == TypeTableEntryIdInvalid) |
| | 8700 | return ira->codegen->builtin_types.entry_invalid; |
| | 8701 | |
| | 8702 | IrInstruction *casted_op2 = ir_implicit_cast(ira, op2, dest_type); |
| | 8703 | if (casted_op2->type_entry->id == TypeTableEntryIdInvalid) |
| | 8704 | return ira->codegen->builtin_types.entry_invalid; |
| | 8705 | |
| | 8706 | IrInstruction *result_ptr = instruction->result_ptr->other; |
| | 8707 | if (result_ptr->type_entry->id == TypeTableEntryIdInvalid) |
| | 8708 | return ira->codegen->builtin_types.entry_invalid; |
| | 8709 | |
| | 8710 | TypeTableEntry *expected_ptr_type = get_pointer_to_type(ira->codegen, dest_type, false); |
| | 8711 | IrInstruction *casted_result_ptr = ir_implicit_cast(ira, result_ptr, expected_ptr_type); |
| | 8712 | if (casted_result_ptr->type_entry->id == TypeTableEntryIdInvalid) |
| | 8713 | return ira->codegen->builtin_types.entry_invalid; |
| | 8714 | |
| | 8715 | if (casted_op1->static_value.special == ConstValSpecialStatic && |
| | 8716 | casted_op2->static_value.special == ConstValSpecialStatic && |
| | 8717 | casted_result_ptr->static_value.special == ConstValSpecialStatic) |
| | 8718 | { |
| | 8719 | bool depends_on_compile_var = type_value->static_value.depends_on_compile_var || |
| | 8720 | casted_op1->static_value.depends_on_compile_var || casted_op2->static_value.depends_on_compile_var || |
| | 8721 | casted_result_ptr->static_value.depends_on_compile_var; |
| | 8722 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base, depends_on_compile_var); |
| | 8723 | BigNum *op1_bignum = &casted_op1->static_value.data.x_bignum; |
| | 8724 | BigNum *op2_bignum = &casted_op2->static_value.data.x_bignum; |
| | 8725 | ConstExprValue *pointee_val = const_ptr_pointee(&casted_result_ptr->static_value); |
| | 8726 | BigNum *dest_bignum = &pointee_val->data.x_bignum; |
| | 8727 | switch (instruction->op) { |
| | 8728 | case IrOverflowOpAdd: |
| | 8729 | out_val->data.x_bool = bignum_add(dest_bignum, op1_bignum, op2_bignum); |
| | 8730 | break; |
| | 8731 | case IrOverflowOpSub: |
| | 8732 | out_val->data.x_bool = bignum_add(dest_bignum, op1_bignum, op2_bignum); |
| | 8733 | break; |
| | 8734 | case IrOverflowOpMul: |
| | 8735 | out_val->data.x_bool = bignum_add(dest_bignum, op1_bignum, op2_bignum); |
| | 8736 | break; |
| | 8737 | case IrOverflowOpShl: |
| | 8738 | out_val->data.x_bool = bignum_add(dest_bignum, op1_bignum, op2_bignum); |
| | 8739 | break; |
| | 8740 | } |
| | 8741 | if (!bignum_fits_in_bits(dest_bignum, canon_type->data.integral.bit_count, |
| | 8742 | canon_type->data.integral.is_signed)) |
| | 8743 | { |
| | 8744 | out_val->data.x_bool = true; |
| | 8745 | bignum_truncate(dest_bignum, canon_type->data.integral.bit_count); |
| | 8746 | } |
| | 8747 | pointee_val->special = ConstValSpecialStatic; |
| | 8748 | return ira->codegen->builtin_types.entry_bool; |
| | 8749 | } |
| | 8750 | |
| | 8751 | ir_build_overflow_op_from(&ira->new_irb, &instruction->base, instruction->op, type_value, |
| | 8752 | casted_op1, casted_op2, casted_result_ptr, dest_type); |
| | 8753 | return ira->codegen->builtin_types.entry_bool; |
| | 8754 | } |
| | 8755 | |
| 8495 | static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) { | 8756 | static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) { |
| 8496 | switch (instruction->id) { | 8757 | switch (instruction->id) { |
| 8497 | case IrInstructionIdInvalid: | 8758 | case IrInstructionIdInvalid: |
| ... | @@ -8618,6 +8879,14 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi | ... | @@ -8618,6 +8879,14 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 8618 | return ir_analyze_instruction_member_count(ira, (IrInstructionMemberCount *)instruction); | 8879 | return ir_analyze_instruction_member_count(ira, (IrInstructionMemberCount *)instruction); |
| 8619 | case IrInstructionIdBreakpoint: | 8880 | case IrInstructionIdBreakpoint: |
| 8620 | return ir_analyze_instruction_breakpoint(ira, (IrInstructionBreakpoint *)instruction); | 8881 | return ir_analyze_instruction_breakpoint(ira, (IrInstructionBreakpoint *)instruction); |
| | 8882 | case IrInstructionIdReturnAddress: |
| | 8883 | return ir_analyze_instruction_return_address(ira, (IrInstructionReturnAddress *)instruction); |
| | 8884 | case IrInstructionIdFrameAddress: |
| | 8885 | return ir_analyze_instruction_frame_address(ira, (IrInstructionFrameAddress *)instruction); |
| | 8886 | case IrInstructionIdAlignOf: |
| | 8887 | return ir_analyze_instruction_alignof(ira, (IrInstructionAlignOf *)instruction); |
| | 8888 | case IrInstructionIdOverflowOp: |
| | 8889 | return ir_analyze_instruction_overflow_op(ira, (IrInstructionOverflowOp *)instruction); |
| 8621 | case IrInstructionIdCast: | 8890 | case IrInstructionIdCast: |
| 8622 | case IrInstructionIdStructFieldPtr: | 8891 | case IrInstructionIdStructFieldPtr: |
| 8623 | case IrInstructionIdEnumFieldPtr: | 8892 | case IrInstructionIdEnumFieldPtr: |
| ... | @@ -8722,6 +8991,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { | ... | @@ -8722,6 +8991,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 8722 | case IrInstructionIdMemset: | 8991 | case IrInstructionIdMemset: |
| 8723 | case IrInstructionIdMemcpy: | 8992 | case IrInstructionIdMemcpy: |
| 8724 | case IrInstructionIdBreakpoint: | 8993 | case IrInstructionIdBreakpoint: |
| | 8994 | case IrInstructionIdOverflowOp: // TODO when we support multiple returns this can be side effect free |
| 8725 | return true; | 8995 | return true; |
| 8726 | case IrInstructionIdPhi: | 8996 | case IrInstructionIdPhi: |
| 8727 | case IrInstructionIdUnOp: | 8997 | case IrInstructionIdUnOp: |
| ... | @@ -8765,6 +9035,9 @@ bool ir_has_side_effects(IrInstruction *instruction) { | ... | @@ -8765,6 +9035,9 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 8765 | case IrInstructionIdAlloca: | 9035 | case IrInstructionIdAlloca: |
| 8766 | case IrInstructionIdSlice: | 9036 | case IrInstructionIdSlice: |
| 8767 | case IrInstructionIdMemberCount: | 9037 | case IrInstructionIdMemberCount: |
| | 9038 | case IrInstructionIdAlignOf: |
| | 9039 | case IrInstructionIdReturnAddress: |
| | 9040 | case IrInstructionIdFrameAddress: |
| 8768 | return false; | 9041 | return false; |
| 8769 | case IrInstructionIdAsm: | 9042 | case IrInstructionIdAsm: |
| 8770 | { | 9043 | { |
| ... | @@ -8776,63 +9049,6 @@ bool ir_has_side_effects(IrInstruction *instruction) { | ... | @@ -8776,63 +9049,6 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 8776 | } | 9049 | } |
| 8777 | | 9050 | |
| 8778 | // TODO port over all this commented out code into new IR way of doing things | 9051 | // TODO port over all this commented out code into new IR way of doing things |
| 8779 | //static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, | | |
| 8780 | // TypeTableEntry *expected_type, AstNode *node) | | |
| 8781 | //{ | | |
| 8782 | // | | |
| 8783 | // switch (builtin_fn->id) { | | |
| 8784 | // case BuiltinFnIdInvalid: | | |
| 8785 | // zig_unreachable(); | | |
| 8786 | // case BuiltinFnIdAddWithOverflow: | | |
| 8787 | // case BuiltinFnIdSubWithOverflow: | | |
| 8788 | // case BuiltinFnIdMulWithOverflow: | | |
| 8789 | // case BuiltinFnIdShlWithOverflow: | | |
| 8790 | // { | | |
| 8791 | // AstNode *type_node = node->data.fn_call_expr.params.at(0); | | |
| 8792 | // TypeTableEntry *int_type = analyze_type_expr(g, import, context, type_node); | | |
| 8793 | // if (int_type->id == TypeTableEntryIdInvalid) { | | |
| 8794 | // return g->builtin_types.entry_bool; | | |
| 8795 | // } else if (int_type->id == TypeTableEntryIdInt) { | | |
| 8796 | // AstNode *op1_node = node->data.fn_call_expr.params.at(1); | | |
| 8797 | // AstNode *op2_node = node->data.fn_call_expr.params.at(2); | | |
| 8798 | // AstNode *result_node = node->data.fn_call_expr.params.at(3); | | |
| 8799 | // | | |
| 8800 | // analyze_expression(g, import, context, int_type, op1_node); | | |
| 8801 | // analyze_expression(g, import, context, int_type, op2_node); | | |
| 8802 | // analyze_expression(g, import, context, get_pointer_to_type(g, int_type, false), | | |
| 8803 | // result_node); | | |
| 8804 | // } else { | | |
| 8805 | // add_node_error(g, type_node, | | |
| 8806 | // buf_sprintf("expected integer type, found '%s'", buf_ptr(&int_type->name))); | | |
| 8807 | // } | | |
| 8808 | // | | |
| 8809 | // // TODO constant expression evaluation | | |
| 8810 | // | | |
| 8811 | // return g->builtin_types.entry_bool; | | |
| 8812 | // } | | |
| 8813 | // case BuiltinFnIdAlignof: | | |
| 8814 | // { | | |
| 8815 | // AstNode *type_node = node->data.fn_call_expr.params.at(0); | | |
| 8816 | // TypeTableEntry *type_entry = analyze_type_expr(g, import, context, type_node); | | |
| 8817 | // if (type_entry->id == TypeTableEntryIdInvalid) { | | |
| 8818 | // return g->builtin_types.entry_invalid; | | |
| 8819 | // } else if (type_entry->id == TypeTableEntryIdUnreachable) { | | |
| 8820 | // add_node_error(g, first_executing_node(type_node), | | |
| 8821 | // buf_sprintf("no align available for type '%s'", buf_ptr(&type_entry->name))); | | |
| 8822 | // return g->builtin_types.entry_invalid; | | |
| 8823 | // } else { | | |
| 8824 | // uint64_t align_in_bytes = LLVMABISizeOfType(g->target_data_ref, type_entry->type_ref); | | |
| 8825 | // return resolve_expr_const_val_as_unsigned_num_lit(g, node, expected_type, | | |
| 8826 | // align_in_bytes, false); | | |
| 8827 | // } | | |
| 8828 | // } | | |
| 8829 | // case BuiltinFnIdReturnAddress: | | |
| 8830 | // case BuiltinFnIdFrameAddress: | | |
| 8831 | // mark_impure_fn(g, context, node); | | |
| 8832 | // return builtin_fn->return_type; | | |
| 8833 | // } | | |
| 8834 | // zig_unreachable(); | | |
| 8835 | //} | | |
| 8836 | | 9052 | |
| 8837 | //static TypeTableEntry *analyze_return_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, | 9053 | //static TypeTableEntry *analyze_return_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| 8838 | // TypeTableEntry *expected_type, AstNode *node) | 9054 | // TypeTableEntry *expected_type, AstNode *node) |
| ... | @@ -8948,110 +9164,6 @@ bool ir_has_side_effects(IrInstruction *instruction) { | ... | @@ -8948,110 +9164,6 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 8948 | // } | 9164 | // } |
| 8949 | //} | 9165 | //} |
| 8950 | // | 9166 | // |
| 8951 | //static LLVMValueRef gen_shl_with_overflow(CodeGen *g, AstNode *node) { | | |
| 8952 | // assert(node->type == NodeTypeFnCallExpr); | | |
| 8953 | // | | |
| 8954 | // size_t fn_call_param_count = node->data.fn_call_expr.params.length; | | |
| 8955 | // assert(fn_call_param_count == 4); | | |
| 8956 | // | | |
| 8957 | // TypeTableEntry *int_type = get_type_for_type_node(node->data.fn_call_expr.params.at(0)); | | |
| 8958 | // assert(int_type->id == TypeTableEntryIdInt); | | |
| 8959 | // | | |
| 8960 | // LLVMValueRef val1 = gen_expr(g, node->data.fn_call_expr.params.at(1)); | | |
| 8961 | // LLVMValueRef val2 = gen_expr(g, node->data.fn_call_expr.params.at(2)); | | |
| 8962 | // LLVMValueRef ptr_result = gen_expr(g, node->data.fn_call_expr.params.at(3)); | | |
| 8963 | // | | |
| 8964 | // LLVMValueRef result = LLVMBuildShl(g->builder, val1, val2, ""); | | |
| 8965 | // LLVMValueRef orig_val; | | |
| 8966 | // if (int_type->data.integral.is_signed) { | | |
| 8967 | // orig_val = LLVMBuildAShr(g->builder, result, val2, ""); | | |
| 8968 | // } else { | | |
| 8969 | // orig_val = LLVMBuildLShr(g->builder, result, val2, ""); | | |
| 8970 | // } | | |
| 8971 | // LLVMValueRef overflow_bit = LLVMBuildICmp(g->builder, LLVMIntNE, val1, orig_val, ""); | | |
| 8972 | // | | |
| 8973 | // LLVMBuildStore(g->builder, result, ptr_result); | | |
| 8974 | // | | |
| 8975 | // return overflow_bit; | | |
| 8976 | //} | | |
| 8977 | // | | |
| 8978 | //static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) { | | |
| 8979 | // assert(node->type == NodeTypeFnCallExpr); | | |
| 8980 | // AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr; | | |
| 8981 | // assert(fn_ref_expr->type == NodeTypeSymbol); | | |
| 8982 | // BuiltinFnEntry *builtin_fn = node->data.fn_call_expr.builtin_fn; | | |
| 8983 | // | | |
| 8984 | // switch (builtin_fn->id) { | | |
| 8985 | // case BuiltinFnIdInvalid: | | |
| 8986 | // case BuiltinFnIdTypeof: | | |
| 8987 | // zig_unreachable(); | | |
| 8988 | // case BuiltinFnIdAddWithOverflow: | | |
| 8989 | // case BuiltinFnIdSubWithOverflow: | | |
| 8990 | // case BuiltinFnIdMulWithOverflow: | | |
| 8991 | // { | | |
| 8992 | // size_t fn_call_param_count = node->data.fn_call_expr.params.length; | | |
| 8993 | // assert(fn_call_param_count == 4); | | |
| 8994 | // | | |
| 8995 | // TypeTableEntry *int_type = get_type_for_type_node(node->data.fn_call_expr.params.at(0)); | | |
| 8996 | // AddSubMul add_sub_mul; | | |
| 8997 | // if (builtin_fn->id == BuiltinFnIdAddWithOverflow) { | | |
| 8998 | // add_sub_mul = AddSubMulAdd; | | |
| 8999 | // } else if (builtin_fn->id == BuiltinFnIdSubWithOverflow) { | | |
| 9000 | // add_sub_mul = AddSubMulSub; | | |
| 9001 | // } else if (builtin_fn->id == BuiltinFnIdMulWithOverflow) { | | |
| 9002 | // add_sub_mul = AddSubMulMul; | | |
| 9003 | // } else { | | |
| 9004 | // zig_unreachable(); | | |
| 9005 | // } | | |
| 9006 | // LLVMValueRef fn_val = get_int_overflow_fn(g, int_type, add_sub_mul); | | |
| 9007 | // | | |
| 9008 | // LLVMValueRef op1 = gen_expr(g, node->data.fn_call_expr.params.at(1)); | | |
| 9009 | // LLVMValueRef op2 = gen_expr(g, node->data.fn_call_expr.params.at(2)); | | |
| 9010 | // LLVMValueRef ptr_result = gen_expr(g, node->data.fn_call_expr.params.at(3)); | | |
| 9011 | // | | |
| 9012 | // LLVMValueRef params[] = { | | |
| 9013 | // op1, | | |
| 9014 | // op2, | | |
| 9015 | // }; | | |
| 9016 | // | | |
| 9017 | // LLVMValueRef result_struct = LLVMBuildCall(g->builder, fn_val, params, 2, ""); | | |
| 9018 | // LLVMValueRef result = LLVMBuildExtractValue(g->builder, result_struct, 0, ""); | | |
| 9019 | // LLVMValueRef overflow_bit = LLVMBuildExtractValue(g->builder, result_struct, 1, ""); | | |
| 9020 | // LLVMBuildStore(g->builder, result, ptr_result); | | |
| 9021 | // | | |
| 9022 | // return overflow_bit; | | |
| 9023 | // } | | |
| 9024 | // case BuiltinFnIdShlWithOverflow: | | |
| 9025 | // return gen_shl_with_overflow(g, node); | | |
| 9026 | // case BuiltinFnIdAlignof: | | |
| 9027 | // case BuiltinFnIdMinValue: | | |
| 9028 | // case BuiltinFnIdMaxValue: | | |
| 9029 | // // caught by constant expression eval codegen | | |
| 9030 | // zig_unreachable(); | | |
| 9031 | // case BuiltinFnIdCompileVar: | | |
| 9032 | // return nullptr; | | |
| 9033 | // case BuiltinFnIdFrameAddress: | | |
| 9034 | // case BuiltinFnIdReturnAddress: | | |
| 9035 | // { | | |
| 9036 | // LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_i32->type_ref); | | |
| 9037 | // return LLVMBuildCall(g->builder, builtin_fn->fn_val, &zero, 1, ""); | | |
| 9038 | // } | | |
| 9039 | // case BuiltinFnIdCmpExchange: | | |
| 9040 | // return gen_cmp_exchange(g, node); | | |
| 9041 | // case BuiltinFnIdFence: | | |
| 9042 | // return gen_fence(g, node); | | |
| 9043 | // case BuiltinFnIdUnreachable: | | |
| 9044 | // zig_panic("moved to ir render"); | | |
| 9045 | // case BuiltinFnIdSetFnTest: | | |
| 9046 | // case BuiltinFnIdSetFnStaticEval: | | |
| 9047 | // case BuiltinFnIdSetFnNoInline: | | |
| 9048 | // case BuiltinFnIdSetDebugSafety: | | |
| 9049 | // // do nothing | | |
| 9050 | // return nullptr; | | |
| 9051 | // } | | |
| 9052 | // zig_unreachable(); | | |
| 9053 | //} | | |
| 9054 | // | | |
| 9055 | //static LLVMValueRef gen_enum_value_expr(CodeGen *g, AstNode *node, TypeTableEntry *enum_type, | 9167 | //static LLVMValueRef gen_enum_value_expr(CodeGen *g, AstNode *node, TypeTableEntry *enum_type, |
| 9056 | // AstNode *arg_node) | 9168 | // AstNode *arg_node) |
| 9057 | //{ | 9169 | //{ |