authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-03-20 22:40:08-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-03-20 22:40:08-07:00
log7598a00f34e91375bc8d4f57e8f5ecbc0d1b4d14
tree75338d2cf30fb9092692d0b447d8e2cd610d3023
parentd8692b8bdb4630f2bb2763cdbe609de7d73b28d8

stage2: fix memory management of ZIR code

* 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 functions

5 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};
336340
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 by342/// 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`.
340pub const Fn = struct {344pub 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` to352 /// 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};
374383
375pub const Var = struct {384pub 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};
15261535
...@@ -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();
20802089
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);
21052115
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();
21562166
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();
21632173
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);
21702180
...@@ -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);
23192329
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);
26842696
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}
28542853
2855fn zirUnreachable(2854fn 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();
28632857
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 },
417417
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);
31673172
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);
31703175
3171 // We handle the different builtins manually because they have different semantics depending3176 // 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 }
31893194
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),
32603269
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 }
17511751
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 else1758 };
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();
17631760
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 }
24632460
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 else2466 };
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();
24742468
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 }
6969
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 blocks77 /// 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 compiler747 /// 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 },
11341148
1135 // Make sure we don't accidentally add a field to make this union1149 // Make sure we don't accidentally add a field to make this union
1136 // bigger than expected. Note that in Debug builds, Zig is allowed1150 // 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),
14141426
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),
14271440
1428 .enum_literal_small => try self.writeSmallStr(stream, inst),1441 .enum_literal_small => try self.writeSmallStr(stream, inst),
14291442
...@@ -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 }
16141627
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,