| author | |
| committer | |
| log | 7598a00f34e91375bc8d4f57e8f5ecbc0d1b4d14 |
| tree | 75338d2cf30fb9092692d0b447d8e2cd610d3023 |
| parent | d8692b8bdb4630f2bb2763cdbe609de7d73b28d8 |
* free Module.Fn ZIR code when destroying the owner Decl
* unreachable_safe and unreachable_unsafe are collapsed into one ZIR
instruction with a safety flag.
* astgen: emit an unreachable instruction for unreachable literals
* don't forget to call deinit on ZIR code
* astgen: implement some builtin functions5 files changed, 114 insertions(+), 84 deletions(-)
src/Module.zig+23-10| ... | @@ -224,6 +224,10 @@ pub const Decl = struct { | ... | @@ -224,6 +224,10 @@ pub const Decl = struct { |
| 224 | const gpa = module.gpa; | 224 | const gpa = module.gpa; |
| 225 | gpa.free(mem.spanZ(decl.name)); | 225 | gpa.free(mem.spanZ(decl.name)); |
| 226 | if (decl.typedValueManaged()) |tvm| { | 226 | if (decl.typedValueManaged()) |tvm| { |
| 227 | if (tvm.typed_value.val.castTag(.function)) |payload| { | ||
| 228 | const func = payload.data; | ||
| 229 | func.deinit(gpa); | ||
| 230 | } | ||
| 227 | tvm.deinit(gpa); | 231 | tvm.deinit(gpa); |
| 228 | } | 232 | } |
| 229 | decl.dependants.deinit(gpa); | 233 | decl.dependants.deinit(gpa); |
| ... | @@ -334,7 +338,7 @@ pub const EmitH = struct { | ... | @@ -334,7 +338,7 @@ pub const EmitH = struct { |
| 334 | fwd_decl: std.ArrayListUnmanaged(u8) = .{}, | 338 | fwd_decl: std.ArrayListUnmanaged(u8) = .{}, |
| 335 | }; | 339 | }; |
| 336 | 340 | ||
| 337 | /// Fn struct memory is owned by the Decl's TypedValue.Managed arena allocator. | 341 | /// Some Fn struct memory is owned by the Decl's TypedValue.Managed arena allocator. |
| 338 | /// Extern functions do not have this data structure; they are represented by | 342 | /// Extern functions do not have this data structure; they are represented by |
| 339 | /// the `Decl` only, with a `Value` tag of `extern_fn`. | 343 | /// the `Decl` only, with a `Value` tag of `extern_fn`. |
| 340 | pub const Fn = struct { | 344 | pub const Fn = struct { |
| ... | @@ -347,6 +351,7 @@ pub const Fn = struct { | ... | @@ -347,6 +351,7 @@ pub const Fn = struct { |
| 347 | /// The number of parameters is determined by referring to the type. | 351 | /// The number of parameters is determined by referring to the type. |
| 348 | /// The first N elements of `extra` are indexes into `string_bytes` to | 352 | /// The first N elements of `extra` are indexes into `string_bytes` to |
| 349 | /// a null-terminated string. | 353 | /// a null-terminated string. |
| 354 | /// This memory is managed with gpa, must be freed when the function is freed. | ||
| 350 | zir: zir.Code, | 355 | zir: zir.Code, |
| 351 | /// undefined unless analysis state is `success`. | 356 | /// undefined unless analysis state is `success`. |
| 352 | body: ir.Body, | 357 | body: ir.Body, |
| ... | @@ -370,6 +375,10 @@ pub const Fn = struct { | ... | @@ -370,6 +375,10 @@ pub const Fn = struct { |
| 370 | pub fn dump(func: *Fn, mod: Module) void { | 375 | pub fn dump(func: *Fn, mod: Module) void { |
| 371 | ir.dumpFn(mod, func); | 376 | ir.dumpFn(mod, func); |
| 372 | } | 377 | } |
| 378 | |||
| 379 | pub fn deinit(func: *Fn, gpa: *Allocator) void { | ||
| 380 | func.zir.deinit(gpa); | ||
| 381 | } | ||
| 373 | }; | 382 | }; |
| 374 | 383 | ||
| 375 | pub const Var = struct { | 384 | pub const Var = struct { |
| ... | @@ -1502,8 +1511,7 @@ pub const WipZirCode = struct { | ... | @@ -1502,8 +1511,7 @@ pub const WipZirCode = struct { |
| 1502 | .ret_node, | 1511 | .ret_node, |
| 1503 | .ret_tok, | 1512 | .ret_tok, |
| 1504 | .ret_coerce, | 1513 | .ret_coerce, |
| 1505 | .unreachable_unsafe, | 1514 | .@"unreachable", |
| 1506 | .unreachable_safe, | ||
| 1507 | .loop, | 1515 | .loop, |
| 1508 | .suspend_block, | 1516 | .suspend_block, |
| 1509 | .suspend_block_one, | 1517 | .suspend_block_one, |
| ... | @@ -1521,6 +1529,7 @@ pub const WipZirCode = struct { | ... | @@ -1521,6 +1529,7 @@ pub const WipZirCode = struct { |
| 1521 | pub fn deinit(wzc: *WipZirCode) void { | 1529 | pub fn deinit(wzc: *WipZirCode) void { |
| 1522 | wzc.instructions.deinit(wzc.gpa); | 1530 | wzc.instructions.deinit(wzc.gpa); |
| 1523 | wzc.extra.deinit(wzc.gpa); | 1531 | wzc.extra.deinit(wzc.gpa); |
| 1532 | wzc.string_bytes.deinit(wzc.gpa); | ||
| 1524 | } | 1533 | } |
| 1525 | }; | 1534 | }; |
| 1526 | 1535 | ||
| ... | @@ -2078,7 +2087,7 @@ fn astgenAndSemaDecl(mod: *Module, decl: *Decl) !bool { | ... | @@ -2078,7 +2087,7 @@ fn astgenAndSemaDecl(mod: *Module, decl: *Decl) !bool { |
| 2078 | var analysis_arena = std.heap.ArenaAllocator.init(mod.gpa); | 2087 | var analysis_arena = std.heap.ArenaAllocator.init(mod.gpa); |
| 2079 | defer analysis_arena.deinit(); | 2088 | defer analysis_arena.deinit(); |
| 2080 | 2089 | ||
| 2081 | const code: zir.Code = blk: { | 2090 | var code: zir.Code = blk: { |
| 2082 | var wip_zir_code: WipZirCode = .{ | 2091 | var wip_zir_code: WipZirCode = .{ |
| 2083 | .decl = decl, | 2092 | .decl = decl, |
| 2084 | .arena = &analysis_arena.allocator, | 2093 | .arena = &analysis_arena.allocator, |
| ... | @@ -2102,6 +2111,7 @@ fn astgenAndSemaDecl(mod: *Module, decl: *Decl) !bool { | ... | @@ -2102,6 +2111,7 @@ fn astgenAndSemaDecl(mod: *Module, decl: *Decl) !bool { |
| 2102 | } | 2111 | } |
| 2103 | break :blk code; | 2112 | break :blk code; |
| 2104 | }; | 2113 | }; |
| 2114 | defer code.deinit(mod.gpa); | ||
| 2105 | 2115 | ||
| 2106 | var sema: Sema = .{ | 2116 | var sema: Sema = .{ |
| 2107 | .mod = mod, | 2117 | .mod = mod, |
| ... | @@ -2154,17 +2164,17 @@ fn astgenAndSemaFn( | ... | @@ -2154,17 +2164,17 @@ fn astgenAndSemaFn( |
| 2154 | var fn_type_scope_arena = std.heap.ArenaAllocator.init(mod.gpa); | 2164 | var fn_type_scope_arena = std.heap.ArenaAllocator.init(mod.gpa); |
| 2155 | defer fn_type_scope_arena.deinit(); | 2165 | defer fn_type_scope_arena.deinit(); |
| 2156 | 2166 | ||
| 2157 | var fn_type_wip_zir_exec: WipZirCode = .{ | 2167 | var fn_type_wip_zir_code: WipZirCode = .{ |
| 2158 | .decl = decl, | 2168 | .decl = decl, |
| 2159 | .arena = &fn_type_scope_arena.allocator, | 2169 | .arena = &fn_type_scope_arena.allocator, |
| 2160 | .gpa = mod.gpa, | 2170 | .gpa = mod.gpa, |
| 2161 | }; | 2171 | }; |
| 2162 | defer fn_type_wip_zir_exec.deinit(); | 2172 | defer fn_type_wip_zir_code.deinit(); |
| 2163 | 2173 | ||
| 2164 | var fn_type_scope: Scope.GenZir = .{ | 2174 | var fn_type_scope: Scope.GenZir = .{ |
| 2165 | .force_comptime = true, | 2175 | .force_comptime = true, |
| 2166 | .parent = &decl.container.base, | 2176 | .parent = &decl.container.base, |
| 2167 | .zir_code = &fn_type_wip_zir_exec, | 2177 | .zir_code = &fn_type_wip_zir_code, |
| 2168 | }; | 2178 | }; |
| 2169 | defer fn_type_scope.instructions.deinit(mod.gpa); | 2179 | defer fn_type_scope.instructions.deinit(mod.gpa); |
| 2170 | 2180 | ||
| ... | @@ -2317,7 +2327,8 @@ fn astgenAndSemaFn( | ... | @@ -2317,7 +2327,8 @@ fn astgenAndSemaFn( |
| 2317 | errdefer decl_arena.deinit(); | 2327 | errdefer decl_arena.deinit(); |
| 2318 | const decl_arena_state = try decl_arena.allocator.create(std.heap.ArenaAllocator.State); | 2328 | const decl_arena_state = try decl_arena.allocator.create(std.heap.ArenaAllocator.State); |
| 2319 | 2329 | ||
| 2320 | const fn_type_code = try fn_type_scope.finish(); | 2330 | var fn_type_code = try fn_type_scope.finish(); |
| 2331 | defer fn_type_code.deinit(mod.gpa); | ||
| 2321 | if (std.builtin.mode == .Debug and mod.comp.verbose_ir) { | 2332 | if (std.builtin.mode == .Debug and mod.comp.verbose_ir) { |
| 2322 | fn_type_code.dump(mod.gpa, "fn_type", &fn_type_scope.base, 0) catch {}; | 2333 | fn_type_code.dump(mod.gpa, "fn_type", &fn_type_scope.base, 0) catch {}; |
| 2323 | } | 2334 | } |
| ... | @@ -2621,7 +2632,8 @@ fn astgenAndSemaVarDecl( | ... | @@ -2621,7 +2632,8 @@ fn astgenAndSemaVarDecl( |
| 2621 | init_result_loc, | 2632 | init_result_loc, |
| 2622 | var_decl.ast.init_node, | 2633 | var_decl.ast.init_node, |
| 2623 | ); | 2634 | ); |
| 2624 | const code = try gen_scope.finish(); | 2635 | var code = try gen_scope.finish(); |
| 2636 | defer code.deinit(mod.gpa); | ||
| 2625 | if (std.builtin.mode == .Debug and mod.comp.verbose_ir) { | 2637 | if (std.builtin.mode == .Debug and mod.comp.verbose_ir) { |
| 2626 | code.dump(mod.gpa, "var_init", &gen_scope.base, 0) catch {}; | 2638 | code.dump(mod.gpa, "var_init", &gen_scope.base, 0) catch {}; |
| 2627 | } | 2639 | } |
| ... | @@ -2683,7 +2695,8 @@ fn astgenAndSemaVarDecl( | ... | @@ -2683,7 +2695,8 @@ fn astgenAndSemaVarDecl( |
| 2683 | defer type_scope.instructions.deinit(mod.gpa); | 2695 | defer type_scope.instructions.deinit(mod.gpa); |
| 2684 | 2696 | ||
| 2685 | const var_type = try astgen.typeExpr(mod, &type_scope.base, var_decl.ast.type_node); | 2697 | const var_type = try astgen.typeExpr(mod, &type_scope.base, var_decl.ast.type_node); |
| 2686 | const code = try type_scope.finish(); | 2698 | var code = try type_scope.finish(); |
| 2699 | defer code.deinit(mod.gpa); | ||
| 2687 | if (std.builtin.mode == .Debug and mod.comp.verbose_ir) { | 2700 | if (std.builtin.mode == .Debug and mod.comp.verbose_ir) { |
| 2688 | code.dump(mod.gpa, "var_type", &type_scope.base, 0) catch {}; | 2701 | code.dump(mod.gpa, "var_type", &type_scope.base, 0) catch {}; |
| 2689 | } | 2702 | } |
src/Sema.zig+5-10| ... | @@ -137,8 +137,7 @@ pub fn analyzeBody(sema: *Sema, block: *Scope.Block, body: []const zir.Inst.Inde | ... | @@ -137,8 +137,7 @@ pub fn analyzeBody(sema: *Sema, block: *Scope.Block, body: []const zir.Inst.Inde |
| 137 | .as_node => try sema.zirAsNode(block, zir_inst), | 137 | .as_node => try sema.zirAsNode(block, zir_inst), |
| 138 | .@"asm" => try sema.zirAsm(block, zir_inst, false), | 138 | .@"asm" => try sema.zirAsm(block, zir_inst, false), |
| 139 | .asm_volatile => try sema.zirAsm(block, zir_inst, true), | 139 | .asm_volatile => try sema.zirAsm(block, zir_inst, true), |
| 140 | .unreachable_safe => try sema.zirUnreachable(block, zir_inst, true), | 140 | .@"unreachable" => try sema.zirUnreachable(block, zir_inst), |
| 141 | .unreachable_unsafe => try sema.zirUnreachable(block, zir_inst, false), | ||
| 142 | .ret_coerce => try sema.zirRetTok(block, zir_inst, true), | 141 | .ret_coerce => try sema.zirRetTok(block, zir_inst, true), |
| 143 | .ret_tok => try sema.zirRetTok(block, zir_inst, false), | 142 | .ret_tok => try sema.zirRetTok(block, zir_inst, false), |
| 144 | .ret_node => try sema.zirRetNode(block, zir_inst), | 143 | .ret_node => try sema.zirRetNode(block, zir_inst), |
| ... | @@ -2852,17 +2851,13 @@ fn zirCondbr(sema: *Sema, parent_block: *Scope.Block, inst: zir.Inst.Index) Inne | ... | @@ -2852,17 +2851,13 @@ fn zirCondbr(sema: *Sema, parent_block: *Scope.Block, inst: zir.Inst.Index) Inne |
| 2852 | return parent_block.addCondBr(src, cond, tzir_then_body, tzir_else_body); | 2851 | return parent_block.addCondBr(src, cond, tzir_then_body, tzir_else_body); |
| 2853 | } | 2852 | } |
| 2854 | 2853 | ||
| 2855 | fn zirUnreachable( | 2854 | fn zirUnreachable(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst { |
| 2856 | sema: *Sema, | ||
| 2857 | block: *Scope.Block, | ||
| 2858 | inst: zir.Inst.Index, | ||
| 2859 | safety_check: bool, | ||
| 2860 | ) InnerError!*Inst { | ||
| 2861 | const tracy = trace(@src()); | 2855 | const tracy = trace(@src()); |
| 2862 | defer tracy.end(); | 2856 | defer tracy.end(); |
| 2863 | 2857 | ||
| 2864 | const src_node = sema.code.instructions.items(.data)[inst].node; | 2858 | const inst_data = sema.code.instructions.items(.data)[inst].@"unreachable"; |
| 2865 | const src: LazySrcLoc = .{ .node_offset = src_node }; | 2859 | const src = inst_data.src(); |
| 2860 | const safety_check = inst_data.safety; | ||
| 2866 | try sema.requireRuntimeBlock(block, src); | 2861 | try sema.requireRuntimeBlock(block, src); |
| 2867 | // TODO Add compile error for @optimizeFor occurring too late in a scope. | 2862 | // TODO Add compile error for @optimizeFor occurring too late in a scope. |
| 2868 | if (safety_check and block.wantSafety()) { | 2863 | if (safety_check and block.wantSafety()) { |
src/astgen.zig+40-31| ... | @@ -415,10 +415,13 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) In | ... | @@ -415,10 +415,13 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) In |
| 415 | return callExpr(mod, scope, rl, node, tree.callFull(node)); | 415 | return callExpr(mod, scope, rl, node, tree.callFull(node)); |
| 416 | }, | 416 | }, |
| 417 | 417 | ||
| 418 | .unreachable_literal => { | 418 | .unreachable_literal => return gz.add(.{ |
| 419 | const result = @enumToInt(zir.Const.unreachable_value); | 419 | .tag = .@"unreachable", |
| 420 | return rvalue(mod, scope, rl, result, node); | 420 | .data = .{ .@"unreachable" = .{ |
| 421 | }, | 421 | .safety = true, |
| 422 | .src_node = gz.zir_code.decl.nodeIndexToRelative(node), | ||
| 423 | } }, | ||
| 424 | }), | ||
| 422 | .@"return" => return ret(mod, scope, node), | 425 | .@"return" => return ret(mod, scope, node), |
| 423 | .field_access => return fieldAccess(mod, scope, rl, node), | 426 | .field_access => return fieldAccess(mod, scope, rl, node), |
| 424 | .float_literal => return floatLiteral(mod, scope, rl, node), | 427 | .float_literal => return floatLiteral(mod, scope, rl, node), |
| ... | @@ -3012,10 +3015,11 @@ fn as( | ... | @@ -3012,10 +3015,11 @@ fn as( |
| 3012 | scope: *Scope, | 3015 | scope: *Scope, |
| 3013 | rl: ResultLoc, | 3016 | rl: ResultLoc, |
| 3014 | builtin_token: ast.TokenIndex, | 3017 | builtin_token: ast.TokenIndex, |
| 3015 | src: usize, | 3018 | node: ast.Node.Index, |
| 3016 | lhs: ast.Node.Index, | 3019 | lhs: ast.Node.Index, |
| 3017 | rhs: ast.Node.Index, | 3020 | rhs: ast.Node.Index, |
| 3018 | ) InnerError!zir.Inst.Ref { | 3021 | ) InnerError!zir.Inst.Ref { |
| 3022 | if (true) @panic("TODO update for zir-memory-layout"); | ||
| 3019 | const dest_type = try typeExpr(mod, scope, lhs); | 3023 | const dest_type = try typeExpr(mod, scope, lhs); |
| 3020 | switch (rl) { | 3024 | switch (rl) { |
| 3021 | .none, .discard, .ref, .ty => { | 3025 | .none, .discard, .ref, .ty => { |
| ... | @@ -3090,10 +3094,11 @@ fn bitCast( | ... | @@ -3090,10 +3094,11 @@ fn bitCast( |
| 3090 | scope: *Scope, | 3094 | scope: *Scope, |
| 3091 | rl: ResultLoc, | 3095 | rl: ResultLoc, |
| 3092 | builtin_token: ast.TokenIndex, | 3096 | builtin_token: ast.TokenIndex, |
| 3093 | src: usize, | 3097 | node: ast.Node.Index, |
| 3094 | lhs: ast.Node.Index, | 3098 | lhs: ast.Node.Index, |
| 3095 | rhs: ast.Node.Index, | 3099 | rhs: ast.Node.Index, |
| 3096 | ) InnerError!zir.Inst.Ref { | 3100 | ) InnerError!zir.Inst.Ref { |
| 3101 | if (true) @panic("TODO update for zir-memory-layout"); | ||
| 3097 | const dest_type = try typeExpr(mod, scope, lhs); | 3102 | const dest_type = try typeExpr(mod, scope, lhs); |
| 3098 | switch (rl) { | 3103 | switch (rl) { |
| 3099 | .none => { | 3104 | .none => { |
| ... | @@ -3138,9 +3143,10 @@ fn typeOf( | ... | @@ -3138,9 +3143,10 @@ fn typeOf( |
| 3138 | scope: *Scope, | 3143 | scope: *Scope, |
| 3139 | rl: ResultLoc, | 3144 | rl: ResultLoc, |
| 3140 | builtin_token: ast.TokenIndex, | 3145 | builtin_token: ast.TokenIndex, |
| 3141 | src: usize, | 3146 | node: ast.Node.Index, |
| 3142 | params: []const ast.Node.Index, | 3147 | params: []const ast.Node.Index, |
| 3143 | ) InnerError!zir.Inst.Ref { | 3148 | ) InnerError!zir.Inst.Ref { |
| 3149 | if (true) @panic("TODO update for zir-memory-layout"); | ||
| 3144 | if (params.len < 1) { | 3150 | if (params.len < 1) { |
| 3145 | return mod.failTok(scope, builtin_token, "expected at least 1 argument, found 0", .{}); | 3151 | return mod.failTok(scope, builtin_token, "expected at least 1 argument, found 0", .{}); |
| 3146 | } | 3152 | } |
| ... | @@ -3158,14 +3164,13 @@ fn builtinCall( | ... | @@ -3158,14 +3164,13 @@ fn builtinCall( |
| 3158 | mod: *Module, | 3164 | mod: *Module, |
| 3159 | scope: *Scope, | 3165 | scope: *Scope, |
| 3160 | rl: ResultLoc, | 3166 | rl: ResultLoc, |
| 3161 | call: ast.Node.Index, | 3167 | node: ast.Node.Index, |
| 3162 | params: []const ast.Node.Index, | 3168 | params: []const ast.Node.Index, |
| 3163 | ) InnerError!zir.Inst.Ref { | 3169 | ) InnerError!zir.Inst.Ref { |
| 3164 | if (true) @panic("TODO update for zir-memory-layout"); | ||
| 3165 | const tree = scope.tree(); | 3170 | const tree = scope.tree(); |
| 3166 | const main_tokens = tree.nodes.items(.main_token); | 3171 | const main_tokens = tree.nodes.items(.main_token); |
| 3167 | 3172 | ||
| 3168 | const builtin_token = main_tokens[call]; | 3173 | const builtin_token = main_tokens[node]; |
| 3169 | const builtin_name = tree.tokenSlice(builtin_token); | 3174 | const builtin_name = tree.tokenSlice(builtin_token); |
| 3170 | 3175 | ||
| 3171 | // We handle the different builtins manually because they have different semantics depending | 3176 | // We handle the different builtins manually because they have different semantics depending |
| ... | @@ -3187,56 +3192,60 @@ fn builtinCall( | ... | @@ -3187,56 +3192,60 @@ fn builtinCall( |
| 3187 | } | 3192 | } |
| 3188 | } | 3193 | } |
| 3189 | 3194 | ||
| 3195 | const gz = scope.getGenZir(); | ||
| 3196 | |||
| 3190 | switch (info.tag) { | 3197 | switch (info.tag) { |
| 3191 | .ptr_to_int => { | 3198 | .ptr_to_int => { |
| 3192 | const operand = try expr(mod, scope, .none, params[0]); | 3199 | const operand = try expr(mod, scope, .none, params[0]); |
| 3193 | const result = try addZIRUnOp(mod, scope, src, .ptrtoint, operand); | 3200 | const result = try gz.addUnNode(.ptrtoint, operand, node); |
| 3194 | return rvalue(mod, scope, rl, result); | 3201 | return rvalue(mod, scope, rl, result, node); |
| 3195 | }, | 3202 | }, |
| 3196 | .float_cast => { | 3203 | .float_cast => { |
| 3204 | if (true) @panic("TODO update for zir-memory-layout"); | ||
| 3197 | const dest_type = try typeExpr(mod, scope, params[0]); | 3205 | const dest_type = try typeExpr(mod, scope, params[0]); |
| 3198 | const rhs = try expr(mod, scope, .none, params[1]); | 3206 | const rhs = try expr(mod, scope, .none, params[1]); |
| 3199 | const result = try addZIRBinOp(mod, scope, src, .floatcast, dest_type, rhs); | 3207 | const result = try addZIRBinOp(mod, scope, src, .floatcast, dest_type, rhs); |
| 3200 | return rvalue(mod, scope, rl, result); | 3208 | return rvalue(mod, scope, rl, result, node); |
| 3201 | }, | 3209 | }, |
| 3202 | .int_cast => { | 3210 | .int_cast => { |
| 3211 | if (true) @panic("TODO update for zir-memory-layout"); | ||
| 3203 | const dest_type = try typeExpr(mod, scope, params[0]); | 3212 | const dest_type = try typeExpr(mod, scope, params[0]); |
| 3204 | const rhs = try expr(mod, scope, .none, params[1]); | 3213 | const rhs = try expr(mod, scope, .none, params[1]); |
| 3205 | const result = try addZIRBinOp(mod, scope, src, .intcast, dest_type, rhs); | 3214 | const result = try addZIRBinOp(mod, scope, src, .intcast, dest_type, rhs); |
| 3206 | return rvalue(mod, scope, rl, result); | 3215 | return rvalue(mod, scope, rl, result, node); |
| 3207 | }, | 3216 | }, |
| 3208 | .breakpoint => { | 3217 | .breakpoint => { |
| 3218 | if (true) @panic("TODO update for zir-memory-layout"); | ||
| 3209 | const result = try addZIRNoOp(mod, scope, src, .breakpoint); | 3219 | const result = try addZIRNoOp(mod, scope, src, .breakpoint); |
| 3210 | return rvalue(mod, scope, rl, result); | 3220 | return rvalue(mod, scope, rl, result, node); |
| 3211 | }, | 3221 | }, |
| 3212 | .import => { | 3222 | .import => { |
| 3213 | const target = try expr(mod, scope, .none, params[0]); | 3223 | const target = try expr(mod, scope, .none, params[0]); |
| 3214 | const result = try addZIRUnOp(mod, scope, src, .import, target); | 3224 | const result = try gz.addUnNode(.import, target, node); |
| 3215 | return rvalue(mod, scope, rl, result); | 3225 | return rvalue(mod, scope, rl, result, node); |
| 3216 | }, | 3226 | }, |
| 3217 | .compile_error => { | 3227 | .compile_error => { |
| 3218 | const target = try expr(mod, scope, .none, params[0]); | 3228 | const target = try expr(mod, scope, .none, params[0]); |
| 3219 | const result = try addZIRUnOp(mod, scope, src, .compile_error, target); | 3229 | const result = try gz.addUnNode(.compile_error, target, node); |
| 3220 | return rvalue(mod, scope, rl, result); | 3230 | return rvalue(mod, scope, rl, result, node); |
| 3221 | }, | 3231 | }, |
| 3222 | .set_eval_branch_quota => { | 3232 | .set_eval_branch_quota => { |
| 3223 | const u32_type = try addZIRInstConst(mod, scope, src, .{ | 3233 | const u32_rl: ResultLoc = .{ .ty = @enumToInt(zir.Const.u32_type) }; |
| 3224 | .ty = Type.initTag(.type), | 3234 | const quota = try expr(mod, scope, u32_rl, params[0]); |
| 3225 | .val = Value.initTag(.u32_type), | 3235 | const result = try gz.addUnNode(.set_eval_branch_quota, quota, node); |
| 3226 | }); | 3236 | return rvalue(mod, scope, rl, result, node); |
| 3227 | const quota = try expr(mod, scope, .{ .ty = u32_type }, params[0]); | ||
| 3228 | const result = try addZIRUnOp(mod, scope, src, .set_eval_branch_quota, quota); | ||
| 3229 | return rvalue(mod, scope, rl, result); | ||
| 3230 | }, | 3237 | }, |
| 3231 | .compile_log => { | 3238 | .compile_log => { |
| 3239 | if (true) @panic("TODO update for zir-memory-layout"); | ||
| 3232 | const arena = scope.arena(); | 3240 | const arena = scope.arena(); |
| 3233 | var targets = try arena.alloc(zir.Inst.Ref, params.len); | 3241 | var targets = try arena.alloc(zir.Inst.Ref, params.len); |
| 3234 | for (params) |param, param_i| | 3242 | for (params) |param, param_i| |
| 3235 | targets[param_i] = try expr(mod, scope, .none, param); | 3243 | targets[param_i] = try expr(mod, scope, .none, param); |
| 3236 | const result = try addZIRInst(mod, scope, src, zir.Inst.CompileLog, .{ .to_log = targets }, .{}); | 3244 | const result = try addZIRInst(mod, scope, src, zir.Inst.CompileLog, .{ .to_log = targets }, .{}); |
| 3237 | return rvalue(mod, scope, rl, result); | 3245 | return rvalue(mod, scope, rl, result, node); |
| 3238 | }, | 3246 | }, |
| 3239 | .field => { | 3247 | .field => { |
| 3248 | if (true) @panic("TODO update for zir-memory-layout"); | ||
| 3240 | const string_type = try addZIRInstConst(mod, scope, src, .{ | 3249 | const string_type = try addZIRInstConst(mod, scope, src, .{ |
| 3241 | .ty = Type.initTag(.type), | 3250 | .ty = Type.initTag(.type), |
| 3242 | .val = Value.initTag(.const_slice_u8_type), | 3251 | .val = Value.initTag(.const_slice_u8_type), |
| ... | @@ -3252,11 +3261,11 @@ fn builtinCall( | ... | @@ -3252,11 +3261,11 @@ fn builtinCall( |
| 3252 | return rvalue(mod, scope, rl, try addZirInstTag(mod, scope, src, .field_val_named, .{ | 3261 | return rvalue(mod, scope, rl, try addZirInstTag(mod, scope, src, .field_val_named, .{ |
| 3253 | .object = try expr(mod, scope, .none, params[0]), | 3262 | .object = try expr(mod, scope, .none, params[0]), |
| 3254 | .field_name = try comptimeExpr(mod, scope, string_rl, params[1]), | 3263 | .field_name = try comptimeExpr(mod, scope, string_rl, params[1]), |
| 3255 | })); | 3264 | }), node); |
| 3256 | }, | 3265 | }, |
| 3257 | .as => return as(mod, scope, rl, builtin_token, src, params[0], params[1]), | 3266 | .as => return as(mod, scope, rl, builtin_token, node, params[0], params[1]), |
| 3258 | .bit_cast => return bitCast(mod, scope, rl, builtin_token, src, params[0], params[1]), | 3267 | .bit_cast => return bitCast(mod, scope, rl, builtin_token, node, params[0], params[1]), |
| 3259 | .TypeOf => return typeOf(mod, scope, rl, builtin_token, src, params), | 3268 | .TypeOf => return typeOf(mod, scope, rl, builtin_token, node, params), |
| 3260 | 3269 | ||
| 3261 | .add_with_overflow, | 3270 | .add_with_overflow, |
| 3262 | .align_cast, | 3271 | .align_cast, |
src/main.zig+13-20| ... | @@ -1750,15 +1750,12 @@ fn buildOutputType( | ... | @@ -1750,15 +1750,12 @@ fn buildOutputType( |
| 1750 | } | 1750 | } |
| 1751 | 1751 | ||
| 1752 | const self_exe_path = try fs.selfExePathAlloc(arena); | 1752 | const self_exe_path = try fs.selfExePathAlloc(arena); |
| 1753 | var zig_lib_directory: Compilation.Directory = if (override_lib_dir) |lib_dir| | 1753 | var zig_lib_directory: Compilation.Directory = if (override_lib_dir) |lib_dir| .{ |
| 1754 | .{ | 1754 | .path = lib_dir, |
| 1755 | .path = lib_dir, | 1755 | .handle = try fs.cwd().openDir(lib_dir, .{}), |
| 1756 | .handle = try fs.cwd().openDir(lib_dir, .{}), | 1756 | } else introspect.findZigLibDirFromSelfExe(arena, self_exe_path) catch |err| { |
| 1757 | } | 1757 | fatal("unable to find zig installation directory: {s}", .{@errorName(err)}); |
| 1758 | else | 1758 | }; |
| 1759 | introspect.findZigLibDirFromSelfExe(arena, self_exe_path) catch |err| { | ||
| 1760 | fatal("unable to find zig installation directory: {s}", .{@errorName(err)}); | ||
| 1761 | }; | ||
| 1762 | defer zig_lib_directory.handle.close(); | 1759 | defer zig_lib_directory.handle.close(); |
| 1763 | 1760 | ||
| 1764 | var thread_pool: ThreadPool = undefined; | 1761 | var thread_pool: ThreadPool = undefined; |
| ... | @@ -2461,15 +2458,12 @@ pub fn cmdBuild(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v | ... | @@ -2461,15 +2458,12 @@ pub fn cmdBuild(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v |
| 2461 | } | 2458 | } |
| 2462 | } | 2459 | } |
| 2463 | 2460 | ||
| 2464 | var zig_lib_directory: Compilation.Directory = if (override_lib_dir) |lib_dir| | 2461 | var zig_lib_directory: Compilation.Directory = if (override_lib_dir) |lib_dir| .{ |
| 2465 | .{ | 2462 | .path = lib_dir, |
| 2466 | .path = lib_dir, | 2463 | .handle = try fs.cwd().openDir(lib_dir, .{}), |
| 2467 | .handle = try fs.cwd().openDir(lib_dir, .{}), | 2464 | } else introspect.findZigLibDirFromSelfExe(arena, self_exe_path) catch |err| { |
| 2468 | } | 2465 | fatal("unable to find zig installation directory: {s}", .{@errorName(err)}); |
| 2469 | else | 2466 | }; |
| 2470 | introspect.findZigLibDirFromSelfExe(arena, self_exe_path) catch |err| { | ||
| 2471 | fatal("unable to find zig installation directory: {s}", .{@errorName(err)}); | ||
| 2472 | }; | ||
| 2473 | defer zig_lib_directory.handle.close(); | 2467 | defer zig_lib_directory.handle.close(); |
| 2474 | 2468 | ||
| 2475 | const std_special = "std" ++ fs.path.sep_str ++ "special"; | 2469 | const std_special = "std" ++ fs.path.sep_str ++ "special"; |
| ... | @@ -3281,8 +3275,7 @@ pub const ClangArgIterator = struct { | ... | @@ -3281,8 +3275,7 @@ pub const ClangArgIterator = struct { |
| 3281 | self.zig_equivalent = clang_arg.zig_equivalent; | 3275 | self.zig_equivalent = clang_arg.zig_equivalent; |
| 3282 | break :find_clang_arg; | 3276 | break :find_clang_arg; |
| 3283 | }, | 3277 | }, |
| 3284 | } | 3278 | } else { |
| 3285 | else { | ||
| 3286 | fatal("Unknown Clang option: '{s}'", .{arg}); | 3279 | fatal("Unknown Clang option: '{s}'", .{arg}); |
| 3287 | } | 3280 | } |
| 3288 | } | 3281 | } |
src/zir.zig+33-13| ... | @@ -67,6 +67,13 @@ pub const Code = struct { | ... | @@ -67,6 +67,13 @@ pub const Code = struct { |
| 67 | return code.string_bytes[index..end :0]; | 67 | return code.string_bytes[index..end :0]; |
| 68 | } | 68 | } |
| 69 | 69 | ||
| 70 | pub fn deinit(code: *Code, gpa: *Allocator) void { | ||
| 71 | code.instructions.deinit(gpa); | ||
| 72 | gpa.free(code.string_bytes); | ||
| 73 | gpa.free(code.extra); | ||
| 74 | code.* = undefined; | ||
| 75 | } | ||
| 76 | |||
| 70 | /// For debugging purposes, like dumpFn but for unanalyzed zir blocks | 77 | /// For debugging purposes, like dumpFn but for unanalyzed zir blocks |
| 71 | pub fn dump( | 78 | pub fn dump( |
| 72 | code: Code, | 79 | code: Code, |
| ... | @@ -737,15 +744,9 @@ pub const Inst = struct { | ... | @@ -737,15 +744,9 @@ pub const Inst = struct { |
| 737 | /// of one or more params. | 744 | /// of one or more params. |
| 738 | /// Uses the `pl_node` field. AST node is the `@TypeOf` call. Payload is `MultiOp`. | 745 | /// Uses the `pl_node` field. AST node is the `@TypeOf` call. Payload is `MultiOp`. |
| 739 | typeof_peer, | 746 | typeof_peer, |
| 740 | /// Asserts control-flow will not reach this instruction. Not safety checked - the compiler | 747 | /// Asserts control-flow will not reach this instruction (`unreachable`). |
| 741 | /// will assume the correctness of this instruction. | 748 | /// Uses the `unreachable` union field. |
| 742 | /// Uses the `node` union field. | 749 | @"unreachable", |
| 743 | unreachable_unsafe, | ||
| 744 | /// Asserts control-flow will not reach this instruction. In safety-checked modes, | ||
| 745 | /// this will generate a call to the panic function unless it can be proven unreachable | ||
| 746 | /// by the compiler. | ||
| 747 | /// Uses the `node` union field. | ||
| 748 | unreachable_safe, | ||
| 749 | /// Bitwise XOR. `^` | 750 | /// Bitwise XOR. `^` |
| 750 | xor, | 751 | xor, |
| 751 | /// Create an optional type '?T' | 752 | /// Create an optional type '?T' |
| ... | @@ -989,8 +990,7 @@ pub const Inst = struct { | ... | @@ -989,8 +990,7 @@ pub const Inst = struct { |
| 989 | .ret_node, | 990 | .ret_node, |
| 990 | .ret_tok, | 991 | .ret_tok, |
| 991 | .ret_coerce, | 992 | .ret_coerce, |
| 992 | .unreachable_unsafe, | 993 | .@"unreachable", |
| 993 | .unreachable_safe, | ||
| 994 | .loop, | 994 | .loop, |
| 995 | .suspend_block, | 995 | .suspend_block, |
| 996 | .suspend_block_one, | 996 | .suspend_block_one, |
| ... | @@ -1131,6 +1131,20 @@ pub const Inst = struct { | ... | @@ -1131,6 +1131,20 @@ pub const Inst = struct { |
| 1131 | callee: Ref, | 1131 | callee: Ref, |
| 1132 | param_index: u32, | 1132 | param_index: u32, |
| 1133 | }, | 1133 | }, |
| 1134 | @"unreachable": struct { | ||
| 1135 | /// Offset from Decl AST node index. | ||
| 1136 | /// `Tag` determines which kind of AST node this points to. | ||
| 1137 | src_node: i32, | ||
| 1138 | /// `false`: Not safety checked - the compiler will assume the | ||
| 1139 | /// correctness of this instruction. | ||
| 1140 | /// `true`: In safety-checked modes, this will generate a call | ||
| 1141 | /// to the panic function unless it can be proven unreachable by the compiler. | ||
| 1142 | safety: bool, | ||
| 1143 | |||
| 1144 | pub fn src(self: @This()) LazySrcLoc { | ||
| 1145 | return .{ .node_offset = self.src_node }; | ||
| 1146 | } | ||
| 1147 | }, | ||
| 1134 | 1148 | ||
| 1135 | // Make sure we don't accidentally add a field to make this union | 1149 | // Make sure we don't accidentally add a field to make this union |
| 1136 | // bigger than expected. Note that in Debug builds, Zig is allowed | 1150 | // bigger than expected. Note that in Debug builds, Zig is allowed |
| ... | @@ -1408,8 +1422,6 @@ const Writer = struct { | ... | @@ -1408,8 +1422,6 @@ const Writer = struct { |
| 1408 | .dbg_stmt_node, | 1422 | .dbg_stmt_node, |
| 1409 | .ret_ptr, | 1423 | .ret_ptr, |
| 1410 | .ret_type, | 1424 | .ret_type, |
| 1411 | .unreachable_unsafe, | ||
| 1412 | .unreachable_safe, | ||
| 1413 | => try self.writeNode(stream, inst), | 1425 | => try self.writeNode(stream, inst), |
| 1414 | 1426 | ||
| 1415 | .decl_ref, | 1427 | .decl_ref, |
| ... | @@ -1424,6 +1436,7 @@ const Writer = struct { | ... | @@ -1424,6 +1436,7 @@ const Writer = struct { |
| 1424 | .fn_type_cc => try self.writeFnTypeCc(stream, inst, false), | 1436 | .fn_type_cc => try self.writeFnTypeCc(stream, inst, false), |
| 1425 | .fn_type_var_args => try self.writeFnType(stream, inst, true), | 1437 | .fn_type_var_args => try self.writeFnType(stream, inst, true), |
| 1426 | .fn_type_cc_var_args => try self.writeFnTypeCc(stream, inst, true), | 1438 | .fn_type_cc_var_args => try self.writeFnTypeCc(stream, inst, true), |
| 1439 | .@"unreachable" => try self.writeUnreachable(stream, inst), | ||
| 1427 | 1440 | ||
| 1428 | .enum_literal_small => try self.writeSmallStr(stream, inst), | 1441 | .enum_literal_small => try self.writeSmallStr(stream, inst), |
| 1429 | 1442 | ||
| ... | @@ -1612,6 +1625,13 @@ const Writer = struct { | ... | @@ -1612,6 +1625,13 @@ const Writer = struct { |
| 1612 | return self.writeFnTypeCommon(stream, param_types, inst_data.return_type, var_args, cc); | 1625 | return self.writeFnTypeCommon(stream, param_types, inst_data.return_type, var_args, cc); |
| 1613 | } | 1626 | } |
| 1614 | 1627 | ||
| 1628 | fn writeUnreachable(self: *Writer, stream: anytype, inst: Inst.Index) !void { | ||
| 1629 | const inst_data = self.code.instructions.items(.data)[inst].@"unreachable"; | ||
| 1630 | const safety_str = if (inst_data.safety) "safe" else "unsafe"; | ||
| 1631 | try stream.print("{s}) ", .{safety_str}); | ||
| 1632 | try self.writeSrc(stream, inst_data.src()); | ||
| 1633 | } | ||
| 1634 | |||
| 1615 | fn writeFnTypeCommon( | 1635 | fn writeFnTypeCommon( |
| 1616 | self: *Writer, | 1636 | self: *Writer, |
| 1617 | stream: anytype, | 1637 | stream: anytype, |