authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-03-25 19:25:26-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-03-25 19:25:26-07:00
logb9c5a1fdf59b16b86d33cb52693e84478295b6a3
treea1a16481e05979c250eea9e735356a894d5b29d8
parent399bb2e154395f1f2372eccb10ea41d6ba5ef68f

astgen: fix for loop expressions

also rename the ZIR instruction `deref_node` to `load`.

5 files changed, 119 insertions(+), 131 deletions(-)

BRANCH_TODO+3
...@@ -35,3 +35,6 @@ Performance optimizations to look into:...@@ -35,3 +35,6 @@ Performance optimizations to look into:
35 * enum literals can use small strings35 * enum literals can use small strings
36 * string literals can use small strings36 * string literals can use small strings
37 * don't need the Sema coercion on condbr condition, it's done with result locations37 * don't need the Sema coercion on condbr condition, it's done with result locations
38 * astgen for loops using pointer arithmetic because it's faster and if the programmer
39 wants an index capture, that will just be a convenience variable that zig sets up
40 independently.
src/Sema.zig+15-15
...@@ -160,7 +160,7 @@ pub fn analyzeBody(...@@ -160,7 +160,7 @@ pub fn analyzeBody(
160 .@"const" => try sema.zirConst(block, inst),160 .@"const" => try sema.zirConst(block, inst),
161 .decl_ref => try sema.zirDeclRef(block, inst),161 .decl_ref => try sema.zirDeclRef(block, inst),
162 .decl_val => try sema.zirDeclVal(block, inst),162 .decl_val => try sema.zirDeclVal(block, inst),
163 .deref_node => try sema.zirDerefNode(block, inst),163 .load => try sema.zirLoad(block, inst),
164 .div => try sema.zirArithmetic(block, inst),164 .div => try sema.zirArithmetic(block, inst),
165 .elem_ptr => try sema.zirElemPtr(block, inst),165 .elem_ptr => try sema.zirElemPtr(block, inst),
166 .elem_ptr_node => try sema.zirElemPtrNode(block, inst),166 .elem_ptr_node => try sema.zirElemPtrNode(block, inst),
...@@ -576,7 +576,7 @@ fn zirIndexablePtrLen(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) In...@@ -576,7 +576,7 @@ fn zirIndexablePtrLen(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) In
576 return sema.mod.failWithOwnedErrorMsg(&block.base, msg);576 return sema.mod.failWithOwnedErrorMsg(&block.base, msg);
577 }577 }
578 const result_ptr = try sema.namedFieldPtr(block, src, array_ptr, "len", src);578 const result_ptr = try sema.namedFieldPtr(block, src, array_ptr, "len", src);
579 return sema.analyzeDeref(block, src, result_ptr, result_ptr.src);579 return sema.analyzeLoad(block, src, result_ptr, result_ptr.src);
580}580}
581581
582fn zirAlloc(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {582fn zirAlloc(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
...@@ -1911,7 +1911,7 @@ fn zirFieldVal(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerErro...@@ -1911,7 +1911,7 @@ fn zirFieldVal(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerErro
1911 const object = try sema.resolveInst(extra.lhs);1911 const object = try sema.resolveInst(extra.lhs);
1912 const object_ptr = try sema.analyzeRef(block, src, object);1912 const object_ptr = try sema.analyzeRef(block, src, object);
1913 const result_ptr = try sema.namedFieldPtr(block, src, object_ptr, field_name, field_name_src);1913 const result_ptr = try sema.namedFieldPtr(block, src, object_ptr, field_name, field_name_src);
1914 return sema.analyzeDeref(block, src, result_ptr, result_ptr.src);1914 return sema.analyzeLoad(block, src, result_ptr, result_ptr.src);
1915}1915}
19161916
1917fn zirFieldPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {1917fn zirFieldPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
...@@ -1939,7 +1939,7 @@ fn zirFieldValNamed(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) Inne...@@ -1939,7 +1939,7 @@ fn zirFieldValNamed(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) Inne
1939 const field_name = try sema.resolveConstString(block, field_name_src, extra.field_name);1939 const field_name = try sema.resolveConstString(block, field_name_src, extra.field_name);
1940 const object_ptr = try sema.analyzeRef(block, src, object);1940 const object_ptr = try sema.analyzeRef(block, src, object);
1941 const result_ptr = try sema.namedFieldPtr(block, src, object_ptr, field_name, field_name_src);1941 const result_ptr = try sema.namedFieldPtr(block, src, object_ptr, field_name, field_name_src);
1942 return sema.analyzeDeref(block, src, result_ptr, src);1942 return sema.analyzeLoad(block, src, result_ptr, src);
1943}1943}
19441944
1945fn zirFieldPtrNamed(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {1945fn zirFieldPtrNamed(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
...@@ -2060,7 +2060,7 @@ fn zirElemVal(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError...@@ -2060,7 +2060,7 @@ fn zirElemVal(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError
2060 const array_ptr = try sema.analyzeRef(block, sema.src, array);2060 const array_ptr = try sema.analyzeRef(block, sema.src, array);
2061 const elem_index = try sema.resolveInst(bin_inst.rhs);2061 const elem_index = try sema.resolveInst(bin_inst.rhs);
2062 const result_ptr = try sema.elemPtr(block, sema.src, array_ptr, elem_index, sema.src);2062 const result_ptr = try sema.elemPtr(block, sema.src, array_ptr, elem_index, sema.src);
2063 return sema.analyzeDeref(block, sema.src, result_ptr, sema.src);2063 return sema.analyzeLoad(block, sema.src, result_ptr, sema.src);
2064}2064}
20652065
2066fn zirElemValNode(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {2066fn zirElemValNode(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
...@@ -2075,7 +2075,7 @@ fn zirElemValNode(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerE...@@ -2075,7 +2075,7 @@ fn zirElemValNode(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerE
2075 const array_ptr = try sema.analyzeRef(block, src, array);2075 const array_ptr = try sema.analyzeRef(block, src, array);
2076 const elem_index = try sema.resolveInst(extra.rhs);2076 const elem_index = try sema.resolveInst(extra.rhs);
2077 const result_ptr = try sema.elemPtr(block, src, array_ptr, elem_index, elem_index_src);2077 const result_ptr = try sema.elemPtr(block, src, array_ptr, elem_index, elem_index_src);
2078 return sema.analyzeDeref(block, src, result_ptr, src);2078 return sema.analyzeLoad(block, src, result_ptr, src);
2079}2079}
20802080
2081fn zirElemPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {2081fn zirElemPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
...@@ -2183,7 +2183,7 @@ fn zirSwitchBr(...@@ -2183,7 +2183,7 @@ fn zirSwitchBr(
21832183
2184 const target_ptr = try sema.resolveInst(inst.positionals.target);2184 const target_ptr = try sema.resolveInst(inst.positionals.target);
2185 const target = if (ref)2185 const target = if (ref)
2186 try sema.analyzeDeref(parent_block, inst.base.src, target_ptr, inst.positionals.target.src)2186 try sema.analyzeLoad(parent_block, inst.base.src, target_ptr, inst.positionals.target.src)
2187 else2187 else
2188 target_ptr;2188 target_ptr;
2189 try sema.validateSwitch(parent_block, target, inst);2189 try sema.validateSwitch(parent_block, target, inst);
...@@ -2639,7 +2639,7 @@ fn analyzeArithmetic(...@@ -2639,7 +2639,7 @@ fn analyzeArithmetic(
2639 return block.addBinOp(src, scalar_type, ir_tag, casted_lhs, casted_rhs);2639 return block.addBinOp(src, scalar_type, ir_tag, casted_lhs, casted_rhs);
2640}2640}
26412641
2642fn zirDerefNode(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {2642fn zirLoad(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
2643 const tracy = trace(@src());2643 const tracy = trace(@src());
2644 defer tracy.end();2644 defer tracy.end();
26452645
...@@ -2647,7 +2647,7 @@ fn zirDerefNode(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerErr...@@ -2647,7 +2647,7 @@ fn zirDerefNode(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerErr
2647 const src = inst_data.src();2647 const src = inst_data.src();
2648 const ptr_src: LazySrcLoc = .{ .node_offset_deref_ptr = inst_data.src_node };2648 const ptr_src: LazySrcLoc = .{ .node_offset_deref_ptr = inst_data.src_node };
2649 const ptr = try sema.resolveInst(inst_data.operand);2649 const ptr = try sema.resolveInst(inst_data.operand);
2650 return sema.analyzeDeref(block, src, ptr, ptr_src);2650 return sema.analyzeLoad(block, src, ptr, ptr_src);
2651}2651}
26522652
2653fn zirAsm(2653fn zirAsm(
...@@ -2958,7 +2958,7 @@ fn zirIsNullPtr(...@@ -2958,7 +2958,7 @@ fn zirIsNullPtr(
2958 const inst_data = sema.code.instructions.items(.data)[inst].un_node;2958 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
2959 const src = inst_data.src();2959 const src = inst_data.src();
2960 const ptr = try sema.resolveInst(inst_data.operand);2960 const ptr = try sema.resolveInst(inst_data.operand);
2961 const loaded = try sema.analyzeDeref(block, src, ptr, src);2961 const loaded = try sema.analyzeLoad(block, src, ptr, src);
2962 return sema.analyzeIsNull(block, src, loaded, invert_logic);2962 return sema.analyzeIsNull(block, src, loaded, invert_logic);
2963}2963}
29642964
...@@ -2978,7 +2978,7 @@ fn zirIsErrPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerErro...@@ -2978,7 +2978,7 @@ fn zirIsErrPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerErro
2978 const inst_data = sema.code.instructions.items(.data)[inst].un_node;2978 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
2979 const src = inst_data.src();2979 const src = inst_data.src();
2980 const ptr = try sema.resolveInst(inst_data.operand);2980 const ptr = try sema.resolveInst(inst_data.operand);
2981 const loaded = try sema.analyzeDeref(block, src, ptr, src);2981 const loaded = try sema.analyzeLoad(block, src, ptr, src);
2982 return sema.analyzeIsErr(block, src, loaded);2982 return sema.analyzeIsErr(block, src, loaded);
2983}2983}
29842984
...@@ -3343,7 +3343,7 @@ fn namedFieldPtr(...@@ -3343,7 +3343,7 @@ fn namedFieldPtr(
3343 },3343 },
3344 .Type => {3344 .Type => {
3345 _ = try sema.resolveConstValue(block, object_ptr.src, object_ptr);3345 _ = try sema.resolveConstValue(block, object_ptr.src, object_ptr);
3346 const result = try sema.analyzeDeref(block, src, object_ptr, object_ptr.src);3346 const result = try sema.analyzeLoad(block, src, object_ptr, object_ptr.src);
3347 const val = result.value().?;3347 const val = result.value().?;
3348 const child_type = try val.toType(sema.arena);3348 const child_type = try val.toType(sema.arena);
3349 switch (child_type.zigTypeTag()) {3349 switch (child_type.zigTypeTag()) {
...@@ -3409,7 +3409,7 @@ fn elemPtr(...@@ -3409,7 +3409,7 @@ fn elemPtr(
34093409
3410 if (elem_ty.isSinglePointer() and elem_ty.elemType().zigTypeTag() == .Array) {3410 if (elem_ty.isSinglePointer() and elem_ty.elemType().zigTypeTag() == .Array) {
3411 // we have to deref the ptr operand to get the actual array pointer3411 // we have to deref the ptr operand to get the actual array pointer
3412 const array_ptr_deref = try sema.analyzeDeref(block, src, array_ptr, array_ptr.src);3412 const array_ptr_deref = try sema.analyzeLoad(block, src, array_ptr, array_ptr.src);
3413 if (array_ptr_deref.value()) |array_ptr_val| {3413 if (array_ptr_deref.value()) |array_ptr_val| {
3414 if (elem_index.value()) |index_val| {3414 if (elem_index.value()) |index_val| {
3415 // Both array pointer and index are compile-time known.3415 // Both array pointer and index are compile-time known.
...@@ -3669,7 +3669,7 @@ fn coerceArrayPtrToMany(sema: *Sema, block: *Scope.Block, dest_type: Type, inst:...@@ -3669,7 +3669,7 @@ fn coerceArrayPtrToMany(sema: *Sema, block: *Scope.Block, dest_type: Type, inst:
36693669
3670fn analyzeDeclVal(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, decl: *Decl) InnerError!*Inst {3670fn analyzeDeclVal(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, decl: *Decl) InnerError!*Inst {
3671 const decl_ref = try sema.analyzeDeclRef(block, src, decl);3671 const decl_ref = try sema.analyzeDeclRef(block, src, decl);
3672 return sema.analyzeDeref(block, src, decl_ref, src);3672 return sema.analyzeLoad(block, src, decl_ref, src);
3673}3673}
36743674
3675fn analyzeDeclRef(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, decl: *Decl) InnerError!*Inst {3675fn analyzeDeclRef(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, decl: *Decl) InnerError!*Inst {
...@@ -3737,7 +3737,7 @@ fn analyzeRef(...@@ -3737,7 +3737,7 @@ fn analyzeRef(
3737 return block.addUnOp(src, ptr_type, .ref, operand);3737 return block.addUnOp(src, ptr_type, .ref, operand);
3738}3738}
37393739
3740fn analyzeDeref(3740fn analyzeLoad(
3741 sema: *Sema,3741 sema: *Sema,
3742 block: *Scope.Block,3742 block: *Scope.Block,
3743 src: LazySrcLoc,3743 src: LazySrcLoc,
src/astgen.zig+55-82
...@@ -443,7 +443,7 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) In...@@ -443,7 +443,7 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) In
443443
444 .deref => {444 .deref => {
445 const lhs = try expr(mod, scope, .none, node_datas[node].lhs);445 const lhs = try expr(mod, scope, .none, node_datas[node].lhs);
446 const result = try gz.addUnNode(.deref_node, lhs, node);446 const result = try gz.addUnNode(.load, lhs, node);
447 return rvalue(mod, scope, rl, result, node);447 return rvalue(mod, scope, rl, result, node);
448 },448 },
449 .address_of => {449 .address_of => {
...@@ -1042,7 +1042,7 @@ fn blockExprStmts(...@@ -1042,7 +1042,7 @@ fn blockExprStmts(
1042 .coerce_result_ptr,1042 .coerce_result_ptr,
1043 .decl_ref,1043 .decl_ref,
1044 .decl_val,1044 .decl_val,
1045 .deref_node,1045 .load,
1046 .div,1046 .div,
1047 .elem_ptr,1047 .elem_ptr,
1048 .elem_val,1048 .elem_val,
...@@ -1396,7 +1396,7 @@ fn assignOp(...@@ -1396,7 +1396,7 @@ fn assignOp(
1396 const gz = scope.getGenZir();1396 const gz = scope.getGenZir();
13971397
1398 const lhs_ptr = try lvalExpr(mod, scope, node_datas[infix_node].lhs);1398 const lhs_ptr = try lvalExpr(mod, scope, node_datas[infix_node].lhs);
1399 const lhs = try gz.addUnNode(.deref_node, lhs_ptr, infix_node);1399 const lhs = try gz.addUnNode(.load, lhs_ptr, infix_node);
1400 const lhs_type = try gz.addUnTok(.typeof, lhs, infix_node);1400 const lhs_type = try gz.addUnTok(.typeof, lhs, infix_node);
1401 const rhs = try expr(mod, scope, .{ .ty = lhs_type }, node_datas[infix_node].rhs);1401 const rhs = try expr(mod, scope, .{ .ty = lhs_type }, node_datas[infix_node].rhs);
14021402
...@@ -2105,7 +2105,7 @@ fn whileExpr(...@@ -2105,7 +2105,7 @@ fn whileExpr(
2105 try checkLabelRedefinition(mod, scope, label_token);2105 try checkLabelRedefinition(mod, scope, label_token);
2106 }2106 }
2107 const parent_gz = scope.getGenZir();2107 const parent_gz = scope.getGenZir();
2108 const is_inline = while_full.inline_token != null;2108 const is_inline = parent_gz.force_comptime or while_full.inline_token != null;
2109 const loop_tag: zir.Inst.Tag = if (is_inline) .block_inline else .loop;2109 const loop_tag: zir.Inst.Tag = if (is_inline) .block_inline else .loop;
2110 const loop_block = try parent_gz.addBlock(loop_tag, node);2110 const loop_block = try parent_gz.addBlock(loop_tag, node);
2111 try parent_gz.instructions.append(mod.gpa, loop_block);2111 try parent_gz.instructions.append(mod.gpa, loop_block);
...@@ -2149,7 +2149,6 @@ fn whileExpr(...@@ -2149,7 +2149,6 @@ fn whileExpr(
2149 // TODO avoid emitting the continue expr when there2149 // TODO avoid emitting the continue expr when there
2150 // are no jumps to it. This happens when the last statement of a while body is noreturn2150 // are no jumps to it. This happens when the last statement of a while body is noreturn
2151 // and there are no `continue` statements.2151 // and there are no `continue` statements.
2152 // The "repeat" at the end of a loop body is implied.
2153 if (while_full.ast.cont_expr != 0) {2152 if (while_full.ast.cont_expr != 0) {
2154 _ = try expr(mod, &loop_scope.base, .{ .ty = .void_type }, while_full.ast.cont_expr);2153 _ = try expr(mod, &loop_scope.base, .{ .ty = .void_type }, while_full.ast.cont_expr);
2155 }2154 }
...@@ -2236,44 +2235,32 @@ fn forExpr(...@@ -2236,44 +2235,32 @@ fn forExpr(
2236 node: ast.Node.Index,2235 node: ast.Node.Index,
2237 for_full: ast.full.While,2236 for_full: ast.full.While,
2238) InnerError!zir.Inst.Ref {2237) InnerError!zir.Inst.Ref {
2239 if (true) @panic("TODO update for zir-memory-layout");
2240 if (for_full.label_token) |label_token| {2238 if (for_full.label_token) |label_token| {
2241 try checkLabelRedefinition(mod, scope, label_token);2239 try checkLabelRedefinition(mod, scope, label_token);
2242 }2240 }
2243
2244 if (for_full.inline_token) |inline_token| {
2245 return mod.failTok(scope, inline_token, "TODO inline for", .{});
2246 }
2247
2248 // Set up variables and constants.2241 // Set up variables and constants.
2249 const parent_gz = scope.getGenZir();2242 const parent_gz = scope.getGenZir();
2243 const is_inline = parent_gz.force_comptime or for_full.inline_token != null;
2250 const tree = parent_gz.tree();2244 const tree = parent_gz.tree();
2251 const main_tokens = tree.nodes.items(.main_token);
2252 const token_tags = tree.tokens.items(.tag);2245 const token_tags = tree.tokens.items(.tag);
22532246
2254 const for_src = token_starts[for_full.ast.while_token];2247 const array_ptr = try expr(mod, scope, .ref, for_full.ast.cond_expr);
2248 const len = try parent_gz.addUnNode(.indexable_ptr_len, array_ptr, for_full.ast.cond_expr);
2249
2255 const index_ptr = blk: {2250 const index_ptr = blk: {
2256 const usize_type = try addZIRInstConst(mod, scope, for_src, .{2251 const index_ptr = try parent_gz.addUnNode(.alloc, .usize_type, node);
2257 .ty = Type.initTag(.type),
2258 .val = Value.initTag(.usize_type),
2259 });
2260 const index_ptr = try addZIRUnOp(mod, scope, for_src, .alloc, usize_type);
2261 // initialize to zero2252 // initialize to zero
2262 const zero = try addZIRInstConst(mod, scope, for_src, .{2253 _ = try parent_gz.addBin(.store, index_ptr, .zero_usize);
2263 .ty = Type.initTag(.usize),
2264 .val = Value.initTag(.zero),
2265 });
2266 _ = try addZIRBinOp(mod, scope, for_src, .store, index_ptr, zero);
2267 break :blk index_ptr;2254 break :blk index_ptr;
2268 };2255 };
2269 const array_ptr = try expr(mod, scope, .ref, for_full.ast.cond_expr);2256
2270 const cond_src = token_starts[tree.firstToken(for_full.ast.cond_expr)];2257 const loop_tag: zir.Inst.Tag = if (is_inline) .block_inline else .loop;
2271 const len = try addZIRUnOp(mod, scope, cond_src, .indexable_ptr_len, array_ptr);2258 const loop_block = try parent_gz.addBlock(loop_tag, node);
2259 try parent_gz.instructions.append(mod.gpa, loop_block);
22722260
2273 var loop_scope: Scope.GenZir = .{2261 var loop_scope: Scope.GenZir = .{
2274 .parent = scope,2262 .parent = scope,
2275 .decl = scope.ownerDecl().?,2263 .zir_code = parent_gz.zir_code,
2276 .arena = scope.arena(),
2277 .force_comptime = parent_gz.force_comptime,2264 .force_comptime = parent_gz.force_comptime,
2278 .instructions = .{},2265 .instructions = .{},
2279 };2266 };
...@@ -2282,66 +2269,49 @@ fn forExpr(...@@ -2282,66 +2269,49 @@ fn forExpr(
22822269
2283 var cond_scope: Scope.GenZir = .{2270 var cond_scope: Scope.GenZir = .{
2284 .parent = &loop_scope.base,2271 .parent = &loop_scope.base,
2285 .decl = loop_scope.decl,2272 .zir_code = parent_gz.zir_code,
2286 .arena = loop_scope.arena,
2287 .force_comptime = loop_scope.force_comptime,2273 .force_comptime = loop_scope.force_comptime,
2288 .instructions = .{},2274 .instructions = .{},
2289 };2275 };
2290 defer cond_scope.instructions.deinit(mod.gpa);2276 defer cond_scope.instructions.deinit(mod.gpa);
22912277
2292 // check condition i < array_expr.len2278 // check condition i < array_expr.len
2293 const index = try addZIRUnOp(mod, &cond_scope.base, cond_src, .deref, index_ptr);2279 const index = try cond_scope.addUnNode(.load, index_ptr, for_full.ast.cond_expr);
2294 const cond = try addZIRBinOp(mod, &cond_scope.base, cond_src, .cmp_lt, index, len);2280 const cond = try cond_scope.addPlNode(.cmp_lt, for_full.ast.cond_expr, zir.Inst.Bin{
22952281 .lhs = index,
2296 const condbr = try addZIRInstSpecial(mod, &cond_scope.base, for_src, zir.Inst.CondBr, .{2282 .rhs = len,
2297 .condition = cond,
2298 .then_body = undefined, // populated below
2299 .else_body = undefined, // populated below
2300 }, .{});
2301 const cond_block = try addZIRInstBlock(mod, &loop_scope.base, for_src, .block, .{
2302 .instructions = try loop_scope.arena.dupe(zir.Inst.Ref, cond_scope.instructions.items),
2303 });2283 });
23042284
2305 // increment index variable2285 const condbr_tag: zir.Inst.Tag = if (is_inline) .condbr_inline else .condbr;
2306 const one = try addZIRInstConst(mod, &loop_scope.base, for_src, .{2286 const condbr = try cond_scope.addCondBr(condbr_tag, node);
2307 .ty = Type.initTag(.usize),2287 const block_tag: zir.Inst.Tag = if (is_inline) .block_inline else .block;
2308 .val = Value.initTag(.one),2288 const cond_block = try loop_scope.addBlock(block_tag, node);
2309 });2289 try loop_scope.instructions.append(mod.gpa, cond_block);
2310 const index_2 = try addZIRUnOp(mod, &loop_scope.base, cond_src, .deref, index_ptr);2290 try cond_scope.setBlockBody(cond_block);
2311 const index_plus_one = try addZIRBinOp(mod, &loop_scope.base, for_src, .add, index_2, one);2291
2312 _ = try addZIRBinOp(mod, &loop_scope.base, for_src, .store, index_ptr, index_plus_one);2292 // Increment the index variable.
23132293 const index_2 = try loop_scope.addUnNode(.load, index_ptr, for_full.ast.cond_expr);
2314 const loop = try scope.arena().create(zir.Inst.Loop);2294 const index_plus_one = try loop_scope.addPlNode(.add, node, zir.Inst.Bin{
2315 loop.* = .{2295 .lhs = index_2,
2316 .base = .{2296 .rhs = .one_usize,
2317 .tag = .loop,
2318 .src = for_src,
2319 },
2320 .positionals = .{
2321 .body = .{
2322 .instructions = try scope.arena().dupe(zir.Inst.Ref, loop_scope.instructions.items),
2323 },
2324 },
2325 .kw_args = .{},
2326 };
2327 const for_block = try addZIRInstBlock(mod, scope, for_src, .block, .{
2328 .instructions = try scope.arena().dupe(zir.Inst.Ref, &[1]zir.Inst.Ref{&loop.base}),
2329 });2297 });
2330 loop_scope.break_block = for_block;2298 _ = try loop_scope.addBin(.store, index_ptr, index_plus_one);
2299 const repeat_tag: zir.Inst.Tag = if (is_inline) .repeat_inline else .repeat;
2300 _ = try loop_scope.addNode(repeat_tag, node);
2301
2302 try loop_scope.setBlockBody(loop_block);
2303 loop_scope.break_block = loop_block;
2331 loop_scope.continue_block = cond_block;2304 loop_scope.continue_block = cond_block;
2332 if (for_full.label_token) |label_token| {2305 if (for_full.label_token) |label_token| {
2333 loop_scope.label = @as(?Scope.GenZir.Label, Scope.GenZir.Label{2306 loop_scope.label = @as(?Scope.GenZir.Label, Scope.GenZir.Label{
2334 .token = label_token,2307 .token = label_token,
2335 .block_inst = for_block,2308 .block_inst = loop_block,
2336 });2309 });
2337 }2310 }
23382311
2339 // while body
2340 const then_src = token_starts[tree.lastToken(for_full.ast.then_expr)];
2341 var then_scope: Scope.GenZir = .{2312 var then_scope: Scope.GenZir = .{
2342 .parent = &cond_scope.base,2313 .parent = &cond_scope.base,
2343 .decl = cond_scope.decl,2314 .zir_code = parent_gz.zir_code,
2344 .arena = cond_scope.arena,
2345 .force_comptime = cond_scope.force_comptime,2315 .force_comptime = cond_scope.force_comptime,
2346 .instructions = .{},2316 .instructions = .{},
2347 };2317 };
...@@ -2375,6 +2345,7 @@ fn forExpr(...@@ -2375,6 +2345,7 @@ fn forExpr(
2375 .gen_zir = &then_scope,2345 .gen_zir = &then_scope,
2376 .name = index_name,2346 .name = index_name,
2377 .ptr = index_ptr,2347 .ptr = index_ptr,
2348 .src = parent_gz.tokSrcLoc(index_token),
2378 };2349 };
2379 break :blk &index_scope.base;2350 break :blk &index_scope.base;
2380 };2351 };
...@@ -2382,34 +2353,36 @@ fn forExpr(...@@ -2382,34 +2353,36 @@ fn forExpr(
2382 loop_scope.break_count += 1;2353 loop_scope.break_count += 1;
2383 const then_result = try expr(mod, then_sub_scope, loop_scope.break_result_loc, for_full.ast.then_expr);2354 const then_result = try expr(mod, then_sub_scope, loop_scope.break_result_loc, for_full.ast.then_expr);
23842355
2385 // else branch
2386 var else_scope: Scope.GenZir = .{2356 var else_scope: Scope.GenZir = .{
2387 .parent = &cond_scope.base,2357 .parent = &cond_scope.base,
2388 .decl = cond_scope.decl,2358 .zir_code = parent_gz.zir_code,
2389 .arena = cond_scope.arena,
2390 .force_comptime = cond_scope.force_comptime,2359 .force_comptime = cond_scope.force_comptime,
2391 .instructions = .{},2360 .instructions = .{},
2392 };2361 };
2393 defer else_scope.instructions.deinit(mod.gpa);2362 defer else_scope.instructions.deinit(mod.gpa);
23942363
2395 const else_node = for_full.ast.else_expr;2364 const else_node = for_full.ast.else_expr;
2396 const else_info: struct { src: usize, result: ?*zir.Inst } = if (else_node != 0) blk: {2365 const else_info: struct {
2366 src: ast.Node.Index,
2367 result: zir.Inst.Ref,
2368 } = if (else_node != 0) blk: {
2397 loop_scope.break_count += 1;2369 loop_scope.break_count += 1;
2398 const sub_scope = &else_scope.base;2370 const sub_scope = &else_scope.base;
2399 break :blk .{2371 break :blk .{
2400 .src = token_starts[tree.lastToken(else_node)],2372 .src = else_node,
2401 .result = try expr(mod, sub_scope, loop_scope.break_result_loc, else_node),2373 .result = try expr(mod, sub_scope, loop_scope.break_result_loc, else_node),
2402 };2374 };
2403 } else .{2375 } else .{
2404 .src = token_starts[tree.lastToken(for_full.ast.then_expr)],2376 .src = for_full.ast.then_expr,
2405 .result = null,2377 .result = .none,
2406 };2378 };
24072379
2408 if (loop_scope.label) |some| {2380 if (loop_scope.label) |some| {
2409 if (!some.used) {2381 if (!some.used) {
2410 return mod.fail(scope, token_starts[some.token], "unused for loop label", .{});2382 return mod.failTok(scope, some.token, "unused for loop label", .{});
2411 }2383 }
2412 }2384 }
2385 const break_tag: zir.Inst.Tag = if (is_inline) .break_inline else .@"break";
2413 return finishThenElseBlock(2386 return finishThenElseBlock(
2414 mod,2387 mod,
2415 scope,2388 scope,
...@@ -2420,13 +2393,13 @@ fn forExpr(...@@ -2420,13 +2393,13 @@ fn forExpr(
2420 &else_scope,2393 &else_scope,
2421 condbr,2394 condbr,
2422 cond,2395 cond,
2423 then_src,2396 for_full.ast.then_expr,
2424 else_info.src,2397 else_info.src,
2425 then_result,2398 then_result,
2426 else_info.result,2399 else_info.result,
2427 for_block,2400 loop_block,
2428 cond_block,2401 cond_block,
2429 .@"break",2402 break_tag,
2430 );2403 );
2431}2404}
24322405
...@@ -2862,7 +2835,7 @@ fn identifier(...@@ -2862,7 +2835,7 @@ fn identifier(
2862 const local_ptr = s.cast(Scope.LocalPtr).?;2835 const local_ptr = s.cast(Scope.LocalPtr).?;
2863 if (mem.eql(u8, local_ptr.name, ident_name)) {2836 if (mem.eql(u8, local_ptr.name, ident_name)) {
2864 if (rl == .ref) return local_ptr.ptr;2837 if (rl == .ref) return local_ptr.ptr;
2865 const loaded = try gz.addUnNode(.deref_node, local_ptr.ptr, ident);2838 const loaded = try gz.addUnNode(.load, local_ptr.ptr, ident);
2866 return rvalue(mod, scope, rl, loaded, ident);2839 return rvalue(mod, scope, rl, loaded, ident);
2867 }2840 }
2868 s = local_ptr.parent;2841 s = local_ptr.parent;
src/zir.zig+15-3
...@@ -281,7 +281,7 @@ pub const Inst = struct {...@@ -281,7 +281,7 @@ pub const Inst = struct {
281 decl_val,281 decl_val,
282 /// Load the value from a pointer. Assumes `x.*` syntax.282 /// Load the value from a pointer. Assumes `x.*` syntax.
283 /// Uses `un_node` field. AST node is the `x.*` syntax.283 /// Uses `un_node` field. AST node is the `x.*` syntax.
284 deref_node,284 load,
285 /// Arithmetic division. Asserts no integer overflow.285 /// Arithmetic division. Asserts no integer overflow.
286 /// Uses the `pl_node` union field. Payload is `Bin`.286 /// Uses the `pl_node` union field. Payload is `Bin`.
287 div,287 div,
...@@ -661,7 +661,7 @@ pub const Inst = struct {...@@ -661,7 +661,7 @@ pub const Inst = struct {
661 .dbg_stmt_node,661 .dbg_stmt_node,
662 .decl_ref,662 .decl_ref,
663 .decl_val,663 .decl_val,
664 .deref_node,664 .load,
665 .div,665 .div,
666 .elem_ptr,666 .elem_ptr,
667 .elem_val,667 .elem_val,
...@@ -841,6 +841,10 @@ pub const Inst = struct {...@@ -841,6 +841,10 @@ pub const Inst = struct {
841 bool_true,841 bool_true,
842 /// `false`842 /// `false`
843 bool_false,843 bool_false,
844 /// `0` (usize)
845 zero_usize,
846 /// `1` (usize)
847 one_usize,
844848
845 _,849 _,
846850
...@@ -1016,10 +1020,18 @@ pub const Inst = struct {...@@ -1016,10 +1020,18 @@ pub const Inst = struct {
1016 .ty = Type.initTag(.comptime_int),1020 .ty = Type.initTag(.comptime_int),
1017 .val = Value.initTag(.zero),1021 .val = Value.initTag(.zero),
1018 },1022 },
1023 .zero_usize = .{
1024 .ty = Type.initTag(.usize),
1025 .val = Value.initTag(.zero),
1026 },
1019 .one = .{1027 .one = .{
1020 .ty = Type.initTag(.comptime_int),1028 .ty = Type.initTag(.comptime_int),
1021 .val = Value.initTag(.one),1029 .val = Value.initTag(.one),
1022 },1030 },
1031 .one_usize = .{
1032 .ty = Type.initTag(.usize),
1033 .val = Value.initTag(.one),
1034 },
1023 .void_value = .{1035 .void_value = .{
1024 .ty = Type.initTag(.void),1036 .ty = Type.initTag(.void),
1025 .val = Value.initTag(.void_value),1037 .val = Value.initTag(.void_value),
...@@ -1377,7 +1389,7 @@ const Writer = struct {...@@ -1377,7 +1389,7 @@ const Writer = struct {
1377 .call_none,1389 .call_none,
1378 .call_none_chkused,1390 .call_none_chkused,
1379 .compile_error,1391 .compile_error,
1380 .deref_node,1392 .load,
1381 .ensure_result_used,1393 .ensure_result_used,
1382 .ensure_result_non_error,1394 .ensure_result_non_error,
1383 .import,1395 .import,
test/stage2/test.zig+31-31
...@@ -968,37 +968,37 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -968,37 +968,37 @@ pub fn addCases(ctx: *TestContext) !void {
968 );968 );
969969
970 // Basic for loop970 // Basic for loop
971 //case.addCompareOutput(971 case.addCompareOutput(
972 // \\export fn _start() noreturn {972 \\export fn _start() noreturn {
973 // \\ for ("hello") |_| print();973 \\ for ("hello") |_| print();
974 // \\974 \\
975 // \\ exit();975 \\ exit();
976 // \\}976 \\}
977 // \\977 \\
978 // \\fn print() void {978 \\fn print() void {
979 // \\ asm volatile ("syscall"979 \\ asm volatile ("syscall"
980 // \\ :980 \\ :
981 // \\ : [number] "{rax}" (1),981 \\ : [number] "{rax}" (1),
982 // \\ [arg1] "{rdi}" (1),982 \\ [arg1] "{rdi}" (1),
983 // \\ [arg2] "{rsi}" (@ptrToInt("hello\n")),983 \\ [arg2] "{rsi}" (@ptrToInt("hello\n")),
984 // \\ [arg3] "{rdx}" (6)984 \\ [arg3] "{rdx}" (6)
985 // \\ : "rcx", "r11", "memory"985 \\ : "rcx", "r11", "memory"
986 // \\ );986 \\ );
987 // \\ return;987 \\ return;
988 // \\}988 \\}
989 // \\989 \\
990 // \\fn exit() noreturn {990 \\fn exit() noreturn {
991 // \\ asm volatile ("syscall"991 \\ asm volatile ("syscall"
992 // \\ :992 \\ :
993 // \\ : [number] "{rax}" (231),993 \\ : [number] "{rax}" (231),
994 // \\ [arg1] "{rdi}" (0)994 \\ [arg1] "{rdi}" (0)
995 // \\ : "rcx", "r11", "memory"995 \\ : "rcx", "r11", "memory"
996 // \\ );996 \\ );
997 // \\ unreachable;997 \\ unreachable;
998 // \\}998 \\}
999 //,999 ,
1000 // "hello\nhello\nhello\nhello\nhello\n",1000 "hello\nhello\nhello\nhello\nhello\n",
1001 //);1001 );
1002 }1002 }
10031003
1004 //{1004 //{