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 {...@@ -1187,6 +1187,8 @@ struct CodeGen {
1187 LLVMValueRef memcpy_fn_val;1187 LLVMValueRef memcpy_fn_val;
1188 LLVMValueRef memset_fn_val;1188 LLVMValueRef memset_fn_val;
1189 LLVMValueRef trap_fn_val;1189 LLVMValueRef trap_fn_val;
1190 LLVMValueRef return_address_fn_val;
1191 LLVMValueRef frame_address_fn_val;
1190 bool error_during_imports;1192 bool error_during_imports;
1191 uint32_t next_node_index;1193 uint32_t next_node_index;
1192 TypeTableEntry *err_tag_type;1194 TypeTableEntry *err_tag_type;
...@@ -1420,6 +1422,10 @@ enum IrInstructionId {...@@ -1420,6 +1422,10 @@ enum IrInstructionId {
1420 IrInstructionIdSlice,1422 IrInstructionIdSlice,
1421 IrInstructionIdMemberCount,1423 IrInstructionIdMemberCount,
1422 IrInstructionIdBreakpoint,1424 IrInstructionIdBreakpoint,
1425 IrInstructionIdReturnAddress,
1426 IrInstructionIdFrameAddress,
1427 IrInstructionIdAlignOf,
1428 IrInstructionIdOverflowOp,
1423};1429};
14241430
1425struct IrInstruction {1431struct IrInstruction {
...@@ -1965,6 +1971,39 @@ struct IrInstructionBreakpoint {...@@ -1965,6 +1971,39 @@ struct IrInstructionBreakpoint {
1965 IrInstruction base;1971 IrInstruction base;
1966};1972};
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
1968enum LValPurpose {2007enum LValPurpose {
1969 LValPurposeNone,2008 LValPurposeNone,
1970 LValPurposeAssign,2009 LValPurposeAssign,
src/analyze.cpp+1-1
...@@ -876,7 +876,7 @@ static IrInstruction *analyze_const_value(CodeGen *g, Scope *scope, AstNode *nod...@@ -876,7 +876,7 @@ static IrInstruction *analyze_const_value(CodeGen *g, Scope *scope, AstNode *nod
876 size_t backward_branch_count = 0;876 size_t backward_branch_count = 0;
877 return ir_eval_const_value(g, scope, node, type_entry,877 return ir_eval_const_value(g, scope, node, type_entry,
878 &backward_branch_count, default_backward_branch_quota,878 &backward_branch_count, default_backward_branch_quota,
879 nullptr, nullptr);879 nullptr, nullptr, node);
880}880}
881881
882TypeTableEntry *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node) {882TypeTableEntry *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...@@ -2058,6 +2058,80 @@ static LLVMValueRef ir_render_breakpoint(CodeGen *g, IrExecutable *executable, I
2058 return nullptr;2058 return nullptr;
2059}2059}
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
2061static void set_debug_location(CodeGen *g, IrInstruction *instruction) {2135static void set_debug_location(CodeGen *g, IrInstruction *instruction) {
2062 AstNode *source_node = instruction->source_node;2136 AstNode *source_node = instruction->source_node;
2063 Scope *scope = instruction->scope;2137 Scope *scope = instruction->scope;
...@@ -2100,6 +2174,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -2100,6 +2174,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
2100 case IrInstructionIdEmbedFile:2174 case IrInstructionIdEmbedFile:
2101 case IrInstructionIdIntType:2175 case IrInstructionIdIntType:
2102 case IrInstructionIdMemberCount:2176 case IrInstructionIdMemberCount:
2177 case IrInstructionIdAlignOf:
2103 zig_unreachable();2178 zig_unreachable();
2104 case IrInstructionIdReturn:2179 case IrInstructionIdReturn:
2105 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);2180 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);
...@@ -2169,6 +2244,12 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -2169,6 +2244,12 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
2169 return ir_render_slice(g, executable, (IrInstructionSlice *)instruction);2244 return ir_render_slice(g, executable, (IrInstructionSlice *)instruction);
2170 case IrInstructionIdBreakpoint:2245 case IrInstructionIdBreakpoint:
2171 return ir_render_breakpoint(g, executable, (IrInstructionBreakpoint *)instruction);2246 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);
2172 case IrInstructionIdSwitchVar:2253 case IrInstructionIdSwitchVar:
2173 case IrInstructionIdContainerInitList:2254 case IrInstructionIdContainerInitList:
2174 case IrInstructionIdStructInit:2255 case IrInstructionIdStructInit:
...@@ -3300,6 +3381,8 @@ static void define_builtin_fns(CodeGen *g) {...@@ -3300,6 +3381,8 @@ static void define_builtin_fns(CodeGen *g) {
3300 &g->builtin_types.entry_i32->type_ref, 1, false);3381 &g->builtin_types.entry_i32->type_ref, 1, false);
3301 builtin_fn->fn_val = LLVMAddFunction(g->module, "llvm.returnaddress", fn_type);3382 builtin_fn->fn_val = LLVMAddFunction(g->module, "llvm.returnaddress", fn_type);
3302 assert(LLVMGetIntrinsicID(builtin_fn->fn_val));3383 assert(LLVMGetIntrinsicID(builtin_fn->fn_val));
3384
3385 g->return_address_fn_val = builtin_fn->fn_val;
3303 }3386 }
3304 {3387 {
3305 BuiltinFnEntry *builtin_fn = create_builtin_fn(g, BuiltinFnIdFrameAddress,3388 BuiltinFnEntry *builtin_fn = create_builtin_fn(g, BuiltinFnIdFrameAddress,
...@@ -3310,6 +3393,8 @@ static void define_builtin_fns(CodeGen *g) {...@@ -3310,6 +3393,8 @@ static void define_builtin_fns(CodeGen *g) {
3310 &g->builtin_types.entry_i32->type_ref, 1, false);3393 &g->builtin_types.entry_i32->type_ref, 1, false);
3311 builtin_fn->fn_val = LLVMAddFunction(g->module, "llvm.frameaddress", fn_type);3394 builtin_fn->fn_val = LLVMAddFunction(g->module, "llvm.frameaddress", fn_type);
3312 assert(LLVMGetIntrinsicID(builtin_fn->fn_val));3395 assert(LLVMGetIntrinsicID(builtin_fn->fn_val));
3396
3397 g->frame_address_fn_val = builtin_fn->fn_val;
3313 }3398 }
3314 {3399 {
3315 BuiltinFnEntry *builtin_fn = create_builtin_fn(g, BuiltinFnIdMemcpy, "memcpy", 3);3400 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 *) {...@@ -395,6 +395,22 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionBreakpoint *) {
395 return IrInstructionIdBreakpoint;395 return IrInstructionIdBreakpoint;
396}396}
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
398template<typename T>414template<typename T>
399static T *ir_create_instruction(IrExecutable *exec, Scope *scope, AstNode *source_node) {415static 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}
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
1635static void ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope,1712static 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}
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
2145static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNode *node) {2250static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNode *node) {
2146 assert(node->type == NodeTypeFnCallExpr);2251 assert(node->type == NodeTypeFnCallExpr);
21472252
...@@ -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 }
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
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 }
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
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}
27732891
...@@ -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
40574175
4058static TypeTableEntry *ir_analyze_const_ptr(IrAnalyze *ira, IrInstruction *instruction,4176static 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) {
40864204
4087IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,4205IrInstruction *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
41224240
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 }
41284246
...@@ -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 }
45044624
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);
52325352
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;
54095535
...@@ -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
60556181
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;
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);
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;
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);
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;
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);
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);
63336465
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;
63896525
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 }
63936530
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 function7854 // 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;
77197861
...@@ -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}
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
8495static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {8756static 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}
87779050
8778// TODO port over all this commented out code into new IR way of doing things9051// 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
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//{
src/ir.hpp+1-1
...@@ -15,7 +15,7 @@ IrInstruction *ir_gen_fn(CodeGen *g, FnTableEntry *fn_entry);...@@ -15,7 +15,7 @@ IrInstruction *ir_gen_fn(CodeGen *g, FnTableEntry *fn_entry);
1515
16IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,16IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,
17 TypeTableEntry *expected_type, size_t *backward_branch_count, size_t backward_branch_quota,17 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
20TypeTableEntry *ir_analyze(CodeGen *g, IrExecutable *old_executable, IrExecutable *new_executable,20TypeTableEntry *ir_analyze(CodeGen *g, IrExecutable *old_executable, IrExecutable *new_executable,
21 TypeTableEntry *expected_type, AstNode *expected_type_source_node);21 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...@@ -816,6 +816,45 @@ static void ir_print_breakpoint(IrPrint *irp, IrInstructionBreakpoint *instructi
816 fprintf(irp->f, "@breakpoint()");816 fprintf(irp->f, "@breakpoint()");
817}817}
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
819static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {858static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
820 ir_print_prefix(irp, instruction);859 ir_print_prefix(irp, instruction);
821 switch (instruction->id) {860 switch (instruction->id) {
...@@ -1016,6 +1055,18 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1016,6 +1055,18 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1016 case IrInstructionIdBreakpoint:1055 case IrInstructionIdBreakpoint:
1017 ir_print_breakpoint(irp, (IrInstructionBreakpoint *)instruction);1056 ir_print_breakpoint(irp, (IrInstructionBreakpoint *)instruction);
1018 break;1057 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;
1019 }1070 }
1020 fprintf(irp->f, "\n");1071 fprintf(irp->f, "\n");
1021}1072}
test/self_hosted2.zig+16
...@@ -329,6 +329,20 @@ fn intTypeBuiltin() {...@@ -329,6 +329,20 @@ fn intTypeBuiltin() {
329329
330}330}
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
332fn assert(ok: bool) {346fn assert(ok: bool) {
333 if (!ok)347 if (!ok)
334 @unreachable();348 @unreachable();
...@@ -361,6 +375,8 @@ fn runAllTests() {...@@ -361,6 +375,8 @@ fn runAllTests() {
361 exactDivision();375 exactDivision();
362 truncate();376 truncate();
363 intTypeBuiltin();377 intTypeBuiltin();
378 overflowIntrinsics();
379 shlWithOverflow();
364}380}
365381
366export nakedcc fn _start() -> unreachable {382export nakedcc fn _start() -> unreachable {