authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-12-13 04:30:41-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-12-13 04:30:41-05:00
log3f3630d7e349361116416dce36d2f69d7c3e318c
tree836ce54c606706f23a0a7524a3628b6e464c051c
parent8bb5f54b292efacc03ff8d7cc6f59ae36c24305d

IR: implement the rest of the builtin functions

* returnAddress * frameAddress * addWithOverflow * subWithOverflow * mulWithOverflow * shlWithOverflow * alignOf

7 files changed, 491 insertions(+), 188 deletions(-)

src/all_types.hpp+39
......@@ -1187,6 +1187,8 @@ struct CodeGen {
11871187 LLVMValueRef memcpy_fn_val;
11881188 LLVMValueRef memset_fn_val;
11891189 LLVMValueRef trap_fn_val;
1190 LLVMValueRef return_address_fn_val;
1191 LLVMValueRef frame_address_fn_val;
11901192 bool error_during_imports;
11911193 uint32_t next_node_index;
11921194 TypeTableEntry *err_tag_type;
......@@ -1420,6 +1422,10 @@ enum IrInstructionId {
14201422 IrInstructionIdSlice,
14211423 IrInstructionIdMemberCount,
14221424 IrInstructionIdBreakpoint,
1425 IrInstructionIdReturnAddress,
1426 IrInstructionIdFrameAddress,
1427 IrInstructionIdAlignOf,
1428 IrInstructionIdOverflowOp,
14231429};
14241430
14251431struct IrInstruction {
......@@ -1965,6 +1971,39 @@ struct IrInstructionBreakpoint {
19651971 IrInstruction base;
19661972};
19671973
1974struct IrInstructionReturnAddress {
1975 IrInstruction base;
1976};
1977
1978struct IrInstructionFrameAddress {
1979 IrInstruction base;
1980};
1981
1982enum IrOverflowOp {
1983 IrOverflowOpAdd,
1984 IrOverflowOpSub,
1985 IrOverflowOpMul,
1986 IrOverflowOpShl,
1987};
1988
1989struct IrInstructionOverflowOp {
1990 IrInstruction base;
1991
1992 IrOverflowOp op;
1993 IrInstruction *type_value;
1994 IrInstruction *op1;
1995 IrInstruction *op2;
1996 IrInstruction *result_ptr;
1997
1998 TypeTableEntry *result_ptr_type;
1999};
2000
2001struct IrInstructionAlignOf {
2002 IrInstruction base;
2003
2004 IrInstruction *type_value;
2005};
2006
19682007enum LValPurpose {
19692008 LValPurposeNone,
19702009 LValPurposeAssign,
src/analyze.cpp+1-1
......@@ -876,7 +876,7 @@ static IrInstruction *analyze_const_value(CodeGen *g, Scope *scope, AstNode *nod
876876 size_t backward_branch_count = 0;
877877 return ir_eval_const_value(g, scope, node, type_entry,
878878 &backward_branch_count, default_backward_branch_quota,
879 nullptr, nullptr);
879 nullptr, nullptr, node);
880880}
881881
882882TypeTableEntry *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node) {
src/codegen.cpp+85
......@@ -2058,6 +2058,80 @@ static LLVMValueRef ir_render_breakpoint(CodeGen *g, IrExecutable *executable, I
20582058 return nullptr;
20592059}
20602060
2061static LLVMValueRef ir_render_return_address(CodeGen *g, IrExecutable *executable,
2062 IrInstructionReturnAddress *instruction)
2063{
2064 LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_i32->type_ref);
2065 return LLVMBuildCall(g->builder, g->return_address_fn_val, &zero, 1, "");
2066}
2067
2068static LLVMValueRef ir_render_frame_address(CodeGen *g, IrExecutable *executable,
2069 IrInstructionFrameAddress *instruction)
2070{
2071 LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_i32->type_ref);
2072 return LLVMBuildCall(g->builder, g->frame_address_fn_val, &zero, 1, "");
2073}
2074
2075static LLVMValueRef render_shl_with_overflow(CodeGen *g, IrInstructionOverflowOp *instruction) {
2076 TypeTableEntry *int_type = get_underlying_type(instruction->result_ptr_type);
2077 assert(int_type->id == TypeTableEntryIdInt);
2078
2079 LLVMValueRef op1 = ir_llvm_value(g, instruction->op1);
2080 LLVMValueRef op2 = ir_llvm_value(g, instruction->op2);
2081 LLVMValueRef ptr_result = ir_llvm_value(g, instruction->result_ptr);
2082
2083 LLVMValueRef result = LLVMBuildShl(g->builder, op1, op2, "");
2084 LLVMValueRef orig_val;
2085 if (int_type->data.integral.is_signed) {
2086 orig_val = LLVMBuildAShr(g->builder, result, op2, "");
2087 } else {
2088 orig_val = LLVMBuildLShr(g->builder, result, op2, "");
2089 }
2090 LLVMValueRef overflow_bit = LLVMBuildICmp(g->builder, LLVMIntNE, op1, orig_val, "");
2091
2092 LLVMBuildStore(g->builder, result, ptr_result);
2093
2094 return overflow_bit;
2095}
2096
2097static LLVMValueRef ir_render_overflow_op(CodeGen *g, IrExecutable *executable, IrInstructionOverflowOp *instruction) {
2098 AddSubMul add_sub_mul;
2099 switch (instruction->op) {
2100 case IrOverflowOpAdd:
2101 add_sub_mul = AddSubMulAdd;
2102 break;
2103 case IrOverflowOpSub:
2104 add_sub_mul = AddSubMulAdd;
2105 break;
2106 case IrOverflowOpMul:
2107 add_sub_mul = AddSubMulAdd;
2108 break;
2109 case IrOverflowOpShl:
2110 return render_shl_with_overflow(g, instruction);
2111 }
2112
2113 TypeTableEntry *int_type = get_underlying_type(instruction->result_ptr_type);
2114 assert(int_type->id == TypeTableEntryIdInt);
2115
2116 LLVMValueRef fn_val = get_int_overflow_fn(g, int_type, add_sub_mul);
2117
2118 LLVMValueRef op1 = ir_llvm_value(g, instruction->op1);
2119 LLVMValueRef op2 = ir_llvm_value(g, instruction->op2);
2120 LLVMValueRef ptr_result = ir_llvm_value(g, instruction->result_ptr);
2121
2122 LLVMValueRef params[] = {
2123 op1,
2124 op2,
2125 };
2126
2127 LLVMValueRef result_struct = LLVMBuildCall(g->builder, fn_val, params, 2, "");
2128 LLVMValueRef result = LLVMBuildExtractValue(g->builder, result_struct, 0, "");
2129 LLVMValueRef overflow_bit = LLVMBuildExtractValue(g->builder, result_struct, 1, "");
2130 LLVMBuildStore(g->builder, result, ptr_result);
2131
2132 return overflow_bit;
2133}
2134
20612135static void set_debug_location(CodeGen *g, IrInstruction *instruction) {
20622136 AstNode *source_node = instruction->source_node;
20632137 Scope *scope = instruction->scope;
......@@ -2100,6 +2174,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
21002174 case IrInstructionIdEmbedFile:
21012175 case IrInstructionIdIntType:
21022176 case IrInstructionIdMemberCount:
2177 case IrInstructionIdAlignOf:
21032178 zig_unreachable();
21042179 case IrInstructionIdReturn:
21052180 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);
......@@ -2169,6 +2244,12 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
21692244 return ir_render_slice(g, executable, (IrInstructionSlice *)instruction);
21702245 case IrInstructionIdBreakpoint:
21712246 return ir_render_breakpoint(g, executable, (IrInstructionBreakpoint *)instruction);
2247 case IrInstructionIdReturnAddress:
2248 return ir_render_return_address(g, executable, (IrInstructionReturnAddress *)instruction);
2249 case IrInstructionIdFrameAddress:
2250 return ir_render_frame_address(g, executable, (IrInstructionFrameAddress *)instruction);
2251 case IrInstructionIdOverflowOp:
2252 return ir_render_overflow_op(g, executable, (IrInstructionOverflowOp *)instruction);
21722253 case IrInstructionIdSwitchVar:
21732254 case IrInstructionIdContainerInitList:
21742255 case IrInstructionIdStructInit:
......@@ -3300,6 +3381,8 @@ static void define_builtin_fns(CodeGen *g) {
33003381 &g->builtin_types.entry_i32->type_ref, 1, false);
33013382 builtin_fn->fn_val = LLVMAddFunction(g->module, "llvm.returnaddress", fn_type);
33023383 assert(LLVMGetIntrinsicID(builtin_fn->fn_val));
3384
3385 g->return_address_fn_val = builtin_fn->fn_val;
33033386 }
33043387 {
33053388 BuiltinFnEntry *builtin_fn = create_builtin_fn(g, BuiltinFnIdFrameAddress,
......@@ -3310,6 +3393,8 @@ static void define_builtin_fns(CodeGen *g) {
33103393 &g->builtin_types.entry_i32->type_ref, 1, false);
33113394 builtin_fn->fn_val = LLVMAddFunction(g->module, "llvm.frameaddress", fn_type);
33123395 assert(LLVMGetIntrinsicID(builtin_fn->fn_val));
3396
3397 g->frame_address_fn_val = builtin_fn->fn_val;
33133398 }
33143399 {
33153400 BuiltinFnEntry *builtin_fn = create_builtin_fn(g, BuiltinFnIdMemcpy, "memcpy", 3);
src/ir.cpp+298-186
......@@ -395,6 +395,22 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionBreakpoint *) {
395395 return IrInstructionIdBreakpoint;
396396}
397397
398static constexpr IrInstructionId ir_instruction_id(IrInstructionReturnAddress *) {
399 return IrInstructionIdReturnAddress;
400}
401
402static constexpr IrInstructionId ir_instruction_id(IrInstructionFrameAddress *) {
403 return IrInstructionIdFrameAddress;
404}
405
406static constexpr IrInstructionId ir_instruction_id(IrInstructionAlignOf *) {
407 return IrInstructionIdAlignOf;
408}
409
410static constexpr IrInstructionId ir_instruction_id(IrInstructionOverflowOp *) {
411 return IrInstructionIdOverflowOp;
412}
413
398414template<typename T>
399415static T *ir_create_instruction(IrExecutable *exec, Scope *scope, AstNode *source_node) {
400416 T *special_instruction = allocate<T>(1);
......@@ -1632,6 +1648,67 @@ static IrInstruction *ir_build_breakpoint_from(IrBuilder *irb, IrInstruction *ol
16321648 return new_instruction;
16331649}
16341650
1651static 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
1656static 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
1662static 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
1667static 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
1673static 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
1693static 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
1703static 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
16351712static void ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope,
16361713 bool gen_error_defers, bool gen_maybe_defers)
16371714{
......@@ -2142,6 +2219,34 @@ static IrInstruction *ir_gen_field_access(IrBuilder *irb, Scope *scope, AstNode
21422219 return ir_build_load_ptr(irb, scope, node, ptr_instruction);
21432220}
21442221
2222static 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
21452250static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNode *node) {
21462251 assert(node->type == NodeTypeFnCallExpr);
21472252
......@@ -2522,14 +2627,27 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
25222627 }
25232628 case BuiltinFnIdBreakpoint:
25242629 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);
25252634 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 }
25262643 case BuiltinFnIdAddWithOverflow:
2644 return ir_gen_overflow_op(irb, scope, node, IrOverflowOpAdd);
25272645 case BuiltinFnIdSubWithOverflow:
2646 return ir_gen_overflow_op(irb, scope, node, IrOverflowOpSub);
25282647 case BuiltinFnIdMulWithOverflow:
2648 return ir_gen_overflow_op(irb, scope, node, IrOverflowOpMul);
25292649 case BuiltinFnIdShlWithOverflow:
2530 case BuiltinFnIdReturnAddress:
2531 case BuiltinFnIdFrameAddress:
2532 zig_panic("TODO IR gen more builtin functions");
2650 return ir_gen_overflow_op(irb, scope, node, IrOverflowOpShl);
25332651 }
25342652 zig_unreachable();
25352653}
......@@ -2749,10 +2867,6 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod
27492867 type_instruction = nullptr;
27502868 }
27512869
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
27562870 bool is_shadowable = false;
27572871 bool is_const = variable_declaration->is_const;
27582872 bool is_extern = variable_declaration->is_extern;
......@@ -2768,6 +2882,10 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod
27682882 return irb->codegen->invalid_instruction;
27692883 }
27702884
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
27712889 return ir_build_var_decl(irb, scope, node, var, type_instruction, init_value);
27722890}
27732891
......@@ -4057,9 +4175,9 @@ static TypeTableEntry *ir_analyze_void(IrAnalyze *ira, IrInstruction *instructio
40574175
40584176static TypeTableEntry *ir_analyze_const_ptr(IrAnalyze *ira, IrInstruction *instruction,
40594177 ConstExprValue *pointee, TypeTableEntry *pointee_type, bool depends_on_compile_var,
4060 ConstPtrSpecial special)
4178 ConstPtrSpecial special, bool ptr_is_const)
40614179{
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);
40634181 ConstExprValue *const_val = ir_build_const_from(ira, instruction,
40644182 depends_on_compile_var || pointee->depends_on_compile_var);
40654183 const_val->data.x_ptr.base_ptr = pointee;
......@@ -4086,7 +4204,7 @@ static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value) {
40864204
40874205IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,
40884206 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)
40904208{
40914209 IrExecutable ir_executable = {0};
40924210 ir_executable.is_inline = true;
......@@ -4122,7 +4240,7 @@ IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node
41224240
41234241 IrInstruction *result = ir_exec_const_result(&analyzed_executable);
41244242 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"));
41264244 return codegen->invalid_instruction;
41274245 }
41284246
......@@ -4499,7 +4617,9 @@ static TypeTableEntry *ir_analyze_ref(IrAnalyze *ira, IrInstruction *source_inst
44994617 ConstExprValue *val = ir_resolve_const(ira, value);
45004618 if (!val)
45014619 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);
45034623 }
45044624
45054625 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
52305350 var->type = result_type;
52315351 assert(var->type);
52325352
5233 if (casted_init_value->static_value.special == ConstValSpecialStatic) {
5353 if (casted_init_value->static_value.special != ConstValSpecialRuntime) {
52345354 if (var->mem_slot_index != SIZE_MAX) {
52355355 assert(var->mem_slot_index < ira->exec_context.mem_slot_count);
52365356 ConstExprValue *mem_slot = &ira->exec_context.mem_slot_list[var->mem_slot_index];
52375357 *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 }
52385363 }
52395364 } else if (var->is_inline) {
52405365 ir_add_error(ira, &decl_var_instruction->base,
......@@ -5403,7 +5528,8 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal
54035528 // Analyze the fn body block like any other constant expression.
54045529 AstNode *body_node = fn_entry->fn_def_node->data.fn_def.body;
54055530 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);
54075533 if (result->type_entry->id == TypeTableEntryIdInvalid)
54085534 return ira->codegen->builtin_types.entry_invalid;
54095535
......@@ -6055,7 +6181,7 @@ static TypeTableEntry *ir_analyze_var_ptr(IrAnalyze *ira, IrInstruction *instruc
60556181
60566182 if (mem_slot && mem_slot->special != ConstValSpecialRuntime) {
60576183 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);
60596185 } else {
60606186 ir_build_var_ptr_from(&ira->new_irb, instruction, var);
60616187 return get_pointer_to_type(ira->codegen, var->type, false);
......@@ -6270,7 +6396,9 @@ static TypeTableEntry *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source
62706396 const_val->special = ConstValSpecialStatic;
62716397 const_val->data.x_fn = fn_entry;
62726398
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);
62746402 }
62756403 case TldIdContainer:
62766404 {
......@@ -6283,7 +6411,9 @@ static TypeTableEntry *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source
62836411 const_val->special = ConstValSpecialStatic;
62846412 const_val->data.x_type = tld_container->type_entry;
62856413
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);
62876417 }
62886418 case TldIdTypeDef:
62896419 {
......@@ -6296,7 +6426,9 @@ static TypeTableEntry *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source
62966426 const_val->special = ConstValSpecialStatic;
62976427 const_val->data.x_type = tld_typedef->type_entry;
62986428
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);
63006432 }
63016433 }
63026434 zig_unreachable();
......@@ -6332,7 +6464,9 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru
63326464 bignum_init_unsigned(&len_val->data.x_bignum, container_type->data.array.len);
63336465
63346466 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);
63366470 } else {
63376471 add_node_error(ira->codegen, source_node,
63386472 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
63636497 TypeEnumField *field = find_enum_type_field(child_type, field_name);
63646498 if (field) {
63656499 if (field->type_entry->id == TypeTableEntryIdVoid) {
6366 return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, create_const_enum_tag(field->value),
6367 child_type, depends_on_compile_var, ConstPtrSpecialNone);
6500 bool ptr_is_const = true;
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);
63686504 } else {
63696505 zig_panic("TODO enum tag type");
63706506 }
......@@ -6387,8 +6523,9 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru
63876523 const_val->special = ConstValSpecialStatic;
63886524 const_val->data.x_pure_err = err_table_entry->value;
63896525
6526 bool ptr_is_const = true;
63906527 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);
63926529 }
63936530
63946531 ir_add_error(ira, &field_ptr_instruction->base,
......@@ -6396,13 +6533,17 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru
63966533 return ira->codegen->builtin_types.entry_invalid;
63976534 } else if (child_type->id == TypeTableEntryIdInt) {
63986535 if (buf_eql_str(field_name, "bit_count")) {
6536 bool ptr_is_const = true;
63996537 return ir_analyze_const_ptr(ira, &field_ptr_instruction->base,
64006538 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);
64026541 } else if (buf_eql_str(field_name, "is_signed")) {
6542 bool ptr_is_const = true;
64036543 return ir_analyze_const_ptr(ira, &field_ptr_instruction->base,
64046544 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);
64066547 } else {
64076548 ir_add_error(ira, &field_ptr_instruction->base,
64086549 buf_sprintf("type '%s' has no member called '%s'",
......@@ -7713,7 +7854,8 @@ static TypeTableEntry *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruc
77137854 // Execute the C import block like an inline function
77147855 TypeTableEntry *void_type = ira->codegen->builtin_types.entry_void;
77157856 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);
77177859 if (result->type_entry->id == TypeTableEntryIdInvalid)
77187860 return ira->codegen->builtin_types.entry_invalid;
77197861
......@@ -8492,6 +8634,125 @@ static TypeTableEntry *ir_analyze_instruction_breakpoint(IrAnalyze *ira, IrInstr
84928634 return ira->codegen->builtin_types.entry_void;
84938635}
84948636
8637static 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
8645static 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
8653static 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
8674static 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
84958756static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {
84968757 switch (instruction->id) {
84978758 case IrInstructionIdInvalid:
......@@ -8618,6 +8879,14 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
86188879 return ir_analyze_instruction_member_count(ira, (IrInstructionMemberCount *)instruction);
86198880 case IrInstructionIdBreakpoint:
86208881 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);
86218890 case IrInstructionIdCast:
86228891 case IrInstructionIdStructFieldPtr:
86238892 case IrInstructionIdEnumFieldPtr:
......@@ -8722,6 +8991,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
87228991 case IrInstructionIdMemset:
87238992 case IrInstructionIdMemcpy:
87248993 case IrInstructionIdBreakpoint:
8994 case IrInstructionIdOverflowOp: // TODO when we support multiple returns this can be side effect free
87258995 return true;
87268996 case IrInstructionIdPhi:
87278997 case IrInstructionIdUnOp:
......@@ -8765,6 +9035,9 @@ bool ir_has_side_effects(IrInstruction *instruction) {
87659035 case IrInstructionIdAlloca:
87669036 case IrInstructionIdSlice:
87679037 case IrInstructionIdMemberCount:
9038 case IrInstructionIdAlignOf:
9039 case IrInstructionIdReturnAddress:
9040 case IrInstructionIdFrameAddress:
87689041 return false;
87699042 case IrInstructionIdAsm:
87709043 {
......@@ -8776,63 +9049,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
87769049}
87779050
87789051// 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//}
88369052
88379053//static TypeTableEntry *analyze_return_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
88389054// TypeTableEntry *expected_type, AstNode *node)
......@@ -8948,110 +9164,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
89489164// }
89499165//}
89509166//
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//
90559167//static LLVMValueRef gen_enum_value_expr(CodeGen *g, AstNode *node, TypeTableEntry *enum_type,
90569168// AstNode *arg_node)
90579169//{
src/ir.hpp+1-1
......@@ -15,7 +15,7 @@ IrInstruction *ir_gen_fn(CodeGen *g, FnTableEntry *fn_entry);
1515
1616IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,
1717 TypeTableEntry *expected_type, size_t *backward_branch_count, size_t backward_branch_quota,
18 FnTableEntry *fn_entry, Buf *c_import_buf);
18 FnTableEntry *fn_entry, Buf *c_import_buf, AstNode *source_node);
1919
2020TypeTableEntry *ir_analyze(CodeGen *g, IrExecutable *old_executable, IrExecutable *new_executable,
2121 TypeTableEntry *expected_type, AstNode *expected_type_source_node);
src/ir_print.cpp+51
......@@ -816,6 +816,45 @@ static void ir_print_breakpoint(IrPrint *irp, IrInstructionBreakpoint *instructi
816816 fprintf(irp->f, "@breakpoint()");
817817}
818818
819static void ir_print_frame_address(IrPrint *irp, IrInstructionFrameAddress *instruction) {
820 fprintf(irp->f, "@frameAddress()");
821}
822
823static void ir_print_return_address(IrPrint *irp, IrInstructionReturnAddress *instruction) {
824 fprintf(irp->f, "@returnAddress()");
825}
826
827static void ir_print_alignof(IrPrint *irp, IrInstructionAlignOf *instruction) {
828 fprintf(irp->f, "@alignOf(");
829 ir_print_other_instruction(irp, instruction->type_value);
830 fprintf(irp->f, ")");
831}
832
833static void ir_print_overflow_op(IrPrint *irp, IrInstructionOverflowOp *instruction) {
834 switch (instruction->op) {
835 case IrOverflowOpAdd:
836 fprintf(irp->f, "@addWithOverflow(");
837 break;
838 case IrOverflowOpSub:
839 fprintf(irp->f, "@subWithOverflow(");
840 break;
841 case IrOverflowOpMul:
842 fprintf(irp->f, "@mulWithOverflow(");
843 break;
844 case IrOverflowOpShl:
845 fprintf(irp->f, "@shlWithOverflow(");
846 break;
847 }
848 ir_print_other_instruction(irp, instruction->type_value);
849 fprintf(irp->f, ", ");
850 ir_print_other_instruction(irp, instruction->op1);
851 fprintf(irp->f, ", ");
852 ir_print_other_instruction(irp, instruction->op2);
853 fprintf(irp->f, ", ");
854 ir_print_other_instruction(irp, instruction->result_ptr);
855 fprintf(irp->f, ")");
856}
857
819858static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
820859 ir_print_prefix(irp, instruction);
821860 switch (instruction->id) {
......@@ -1016,6 +1055,18 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
10161055 case IrInstructionIdBreakpoint:
10171056 ir_print_breakpoint(irp, (IrInstructionBreakpoint *)instruction);
10181057 break;
1058 case IrInstructionIdReturnAddress:
1059 ir_print_return_address(irp, (IrInstructionReturnAddress *)instruction);
1060 break;
1061 case IrInstructionIdFrameAddress:
1062 ir_print_frame_address(irp, (IrInstructionFrameAddress *)instruction);
1063 break;
1064 case IrInstructionIdAlignOf:
1065 ir_print_alignof(irp, (IrInstructionAlignOf *)instruction);
1066 break;
1067 case IrInstructionIdOverflowOp:
1068 ir_print_overflow_op(irp, (IrInstructionOverflowOp *)instruction);
1069 break;
10191070 }
10201071 fprintf(irp->f, "\n");
10211072}
test/self_hosted2.zig+16
......@@ -329,6 +329,20 @@ fn intTypeBuiltin() {
329329
330330}
331331
332fn overflowIntrinsics() {
333 var result: u8 = undefined;
334 assert(@addWithOverflow(u8, 250, 100, &result));
335 assert(!@addWithOverflow(u8, 100, 150, &result));
336 assert(result == 250);
337}
338
339fn shlWithOverflow() {
340 var result: u16 = undefined;
341 assert(@shlWithOverflow(u16, 0b0010111111111111, 3, &result));
342 assert(!@shlWithOverflow(u16, 0b0010111111111111, 2, &result));
343 assert(result == 0b1011111111111100);
344}
345
332346fn assert(ok: bool) {
333347 if (!ok)
334348 @unreachable();
......@@ -361,6 +375,8 @@ fn runAllTests() {
361375 exactDivision();
362376 truncate();
363377 intTypeBuiltin();
378 overflowIntrinsics();
379 shlWithOverflow();
364380}
365381
366382export nakedcc fn _start() -> unreachable {