| author | |
| committer | |
| log | b9c5a1fdf59b16b86d33cb52693e84478295b6a3 |
| tree | a1a16481e05979c250eea9e735356a894d5b29d8 |
| parent | 399bb2e154395f1f2372eccb10ea41d6ba5ef68f |
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 | 35 | * enum literals can use small strings |
| 36 | 36 | * string literals can use small strings |
| 37 | 37 | * 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 | 160 | .@"const" => try sema.zirConst(block, inst), |
| 161 | 161 | .decl_ref => try sema.zirDeclRef(block, inst), |
| 162 | 162 | .decl_val => try sema.zirDeclVal(block, inst), |
| 163 | .deref_node => try sema.zirDerefNode(block, inst), | |
| 163 | .load => try sema.zirLoad(block, inst), | |
| 164 | 164 | .div => try sema.zirArithmetic(block, inst), |
| 165 | 165 | .elem_ptr => try sema.zirElemPtr(block, inst), |
| 166 | 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 | 576 | return sema.mod.failWithOwnedErrorMsg(&block.base, msg); |
| 577 | 577 | } |
| 578 | 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 | } |
| 581 | 581 | |
| 582 | 582 | fn 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 | 1911 | const object = try sema.resolveInst(extra.lhs); |
| 1912 | 1912 | const object_ptr = try sema.analyzeRef(block, src, object); |
| 1913 | 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 | } |
| 1916 | 1916 | |
| 1917 | 1917 | fn 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 | 1939 | const field_name = try sema.resolveConstString(block, field_name_src, extra.field_name); |
| 1940 | 1940 | const object_ptr = try sema.analyzeRef(block, src, object); |
| 1941 | 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 | } |
| 1944 | 1944 | |
| 1945 | 1945 | fn 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 | 2060 | const array_ptr = try sema.analyzeRef(block, sema.src, array); |
| 2061 | 2061 | const elem_index = try sema.resolveInst(bin_inst.rhs); |
| 2062 | 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 | } |
| 2065 | 2065 | |
| 2066 | 2066 | fn 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 | 2075 | const array_ptr = try sema.analyzeRef(block, src, array); |
| 2076 | 2076 | const elem_index = try sema.resolveInst(extra.rhs); |
| 2077 | 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 | } |
| 2080 | 2080 | |
| 2081 | 2081 | fn zirElemPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst { |
| ... | ... | @@ -2183,7 +2183,7 @@ fn zirSwitchBr( |
| 2183 | 2183 | |
| 2184 | 2184 | const target_ptr = try sema.resolveInst(inst.positionals.target); |
| 2185 | 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 | 2187 | else |
| 2188 | 2188 | target_ptr; |
| 2189 | 2189 | try sema.validateSwitch(parent_block, target, inst); |
| ... | ... | @@ -2639,7 +2639,7 @@ fn analyzeArithmetic( |
| 2639 | 2639 | return block.addBinOp(src, scalar_type, ir_tag, casted_lhs, casted_rhs); |
| 2640 | 2640 | } |
| 2641 | 2641 | |
| 2642 | fn zirDerefNode(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst { | |
| 2642 | fn zirLoad(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst { | |
| 2643 | 2643 | const tracy = trace(@src()); |
| 2644 | 2644 | defer tracy.end(); |
| 2645 | 2645 | |
| ... | ... | @@ -2647,7 +2647,7 @@ fn zirDerefNode(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerErr |
| 2647 | 2647 | const src = inst_data.src(); |
| 2648 | 2648 | const ptr_src: LazySrcLoc = .{ .node_offset_deref_ptr = inst_data.src_node }; |
| 2649 | 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 | } |
| 2652 | 2652 | |
| 2653 | 2653 | fn zirAsm( |
| ... | ... | @@ -2958,7 +2958,7 @@ fn zirIsNullPtr( |
| 2958 | 2958 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 2959 | 2959 | const src = inst_data.src(); |
| 2960 | 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 | 2962 | return sema.analyzeIsNull(block, src, loaded, invert_logic); |
| 2963 | 2963 | } |
| 2964 | 2964 | |
| ... | ... | @@ -2978,7 +2978,7 @@ fn zirIsErrPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerErro |
| 2978 | 2978 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 2979 | 2979 | const src = inst_data.src(); |
| 2980 | 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 | 2982 | return sema.analyzeIsErr(block, src, loaded); |
| 2983 | 2983 | } |
| 2984 | 2984 | |
| ... | ... | @@ -3343,7 +3343,7 @@ fn namedFieldPtr( |
| 3343 | 3343 | }, |
| 3344 | 3344 | .Type => { |
| 3345 | 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 | 3347 | const val = result.value().?; |
| 3348 | 3348 | const child_type = try val.toType(sema.arena); |
| 3349 | 3349 | switch (child_type.zigTypeTag()) { |
| ... | ... | @@ -3409,7 +3409,7 @@ fn elemPtr( |
| 3409 | 3409 | |
| 3410 | 3410 | if (elem_ty.isSinglePointer() and elem_ty.elemType().zigTypeTag() == .Array) { |
| 3411 | 3411 | // 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 | 3413 | if (array_ptr_deref.value()) |array_ptr_val| { |
| 3414 | 3414 | if (elem_index.value()) |index_val| { |
| 3415 | 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 | 3669 | |
| 3670 | 3670 | fn analyzeDeclVal(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, decl: *Decl) InnerError!*Inst { |
| 3671 | 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 | } |
| 3674 | 3674 | |
| 3675 | 3675 | fn analyzeDeclRef(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, decl: *Decl) InnerError!*Inst { |
| ... | ... | @@ -3737,7 +3737,7 @@ fn analyzeRef( |
| 3737 | 3737 | return block.addUnOp(src, ptr_type, .ref, operand); |
| 3738 | 3738 | } |
| 3739 | 3739 | |
| 3740 | fn analyzeDeref( | |
| 3740 | fn analyzeLoad( | |
| 3741 | 3741 | sema: *Sema, |
| 3742 | 3742 | block: *Scope.Block, |
| 3743 | 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 | 443 | |
| 444 | 444 | .deref => { |
| 445 | 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 | 447 | return rvalue(mod, scope, rl, result, node); |
| 448 | 448 | }, |
| 449 | 449 | .address_of => { |
| ... | ... | @@ -1042,7 +1042,7 @@ fn blockExprStmts( |
| 1042 | 1042 | .coerce_result_ptr, |
| 1043 | 1043 | .decl_ref, |
| 1044 | 1044 | .decl_val, |
| 1045 | .deref_node, | |
| 1045 | .load, | |
| 1046 | 1046 | .div, |
| 1047 | 1047 | .elem_ptr, |
| 1048 | 1048 | .elem_val, |
| ... | ... | @@ -1396,7 +1396,7 @@ fn assignOp( |
| 1396 | 1396 | const gz = scope.getGenZir(); |
| 1397 | 1397 | |
| 1398 | 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 | 1400 | const lhs_type = try gz.addUnTok(.typeof, lhs, infix_node); |
| 1401 | 1401 | const rhs = try expr(mod, scope, .{ .ty = lhs_type }, node_datas[infix_node].rhs); |
| 1402 | 1402 | |
| ... | ... | @@ -2105,7 +2105,7 @@ fn whileExpr( |
| 2105 | 2105 | try checkLabelRedefinition(mod, scope, label_token); |
| 2106 | 2106 | } |
| 2107 | 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 | 2109 | const loop_tag: zir.Inst.Tag = if (is_inline) .block_inline else .loop; |
| 2110 | 2110 | const loop_block = try parent_gz.addBlock(loop_tag, node); |
| 2111 | 2111 | try parent_gz.instructions.append(mod.gpa, loop_block); |
| ... | ... | @@ -2149,7 +2149,6 @@ fn whileExpr( |
| 2149 | 2149 | // TODO avoid emitting the continue expr when there |
| 2150 | 2150 | // are no jumps to it. This happens when the last statement of a while body is noreturn |
| 2151 | 2151 | // and there are no `continue` statements. |
| 2152 | // The "repeat" at the end of a loop body is implied. | |
| 2153 | 2152 | if (while_full.ast.cont_expr != 0) { |
| 2154 | 2153 | _ = try expr(mod, &loop_scope.base, .{ .ty = .void_type }, while_full.ast.cont_expr); |
| 2155 | 2154 | } |
| ... | ... | @@ -2236,44 +2235,32 @@ fn forExpr( |
| 2236 | 2235 | node: ast.Node.Index, |
| 2237 | 2236 | for_full: ast.full.While, |
| 2238 | 2237 | ) InnerError!zir.Inst.Ref { |
| 2239 | if (true) @panic("TODO update for zir-memory-layout"); | |
| 2240 | 2238 | if (for_full.label_token) |label_token| { |
| 2241 | 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 | 2241 | // Set up variables and constants. |
| 2249 | 2242 | const parent_gz = scope.getGenZir(); |
| 2243 | const is_inline = parent_gz.force_comptime or for_full.inline_token != null; | |
| 2250 | 2244 | const tree = parent_gz.tree(); |
| 2251 | const main_tokens = tree.nodes.items(.main_token); | |
| 2252 | 2245 | const token_tags = tree.tokens.items(.tag); |
| 2253 | 2246 | |
| 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 | 2250 | const index_ptr = blk: { |
| 2256 | const usize_type = try addZIRInstConst(mod, scope, for_src, .{ | |
| 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); | |
| 2251 | const index_ptr = try parent_gz.addUnNode(.alloc, .usize_type, node); | |
| 2261 | 2252 | // initialize to zero |
| 2262 | const zero = try addZIRInstConst(mod, scope, for_src, .{ | |
| 2263 | .ty = Type.initTag(.usize), | |
| 2264 | .val = Value.initTag(.zero), | |
| 2265 | }); | |
| 2266 | _ = try addZIRBinOp(mod, scope, for_src, .store, index_ptr, zero); | |
| 2253 | _ = try parent_gz.addBin(.store, index_ptr, .zero_usize); | |
| 2267 | 2254 | break :blk index_ptr; |
| 2268 | 2255 | }; |
| 2269 | const array_ptr = try expr(mod, scope, .ref, for_full.ast.cond_expr); | |
| 2270 | const cond_src = token_starts[tree.firstToken(for_full.ast.cond_expr)]; | |
| 2271 | const len = try addZIRUnOp(mod, scope, cond_src, .indexable_ptr_len, array_ptr); | |
| 2256 | ||
| 2257 | const loop_tag: zir.Inst.Tag = if (is_inline) .block_inline else .loop; | |
| 2258 | const loop_block = try parent_gz.addBlock(loop_tag, node); | |
| 2259 | try parent_gz.instructions.append(mod.gpa, loop_block); | |
| 2272 | 2260 | |
| 2273 | 2261 | var loop_scope: Scope.GenZir = .{ |
| 2274 | 2262 | .parent = scope, |
| 2275 | .decl = scope.ownerDecl().?, | |
| 2276 | .arena = scope.arena(), | |
| 2263 | .zir_code = parent_gz.zir_code, | |
| 2277 | 2264 | .force_comptime = parent_gz.force_comptime, |
| 2278 | 2265 | .instructions = .{}, |
| 2279 | 2266 | }; |
| ... | ... | @@ -2282,66 +2269,49 @@ fn forExpr( |
| 2282 | 2269 | |
| 2283 | 2270 | var cond_scope: Scope.GenZir = .{ |
| 2284 | 2271 | .parent = &loop_scope.base, |
| 2285 | .decl = loop_scope.decl, | |
| 2286 | .arena = loop_scope.arena, | |
| 2272 | .zir_code = parent_gz.zir_code, | |
| 2287 | 2273 | .force_comptime = loop_scope.force_comptime, |
| 2288 | 2274 | .instructions = .{}, |
| 2289 | 2275 | }; |
| 2290 | 2276 | defer cond_scope.instructions.deinit(mod.gpa); |
| 2291 | 2277 | |
| 2292 | 2278 | // check condition i < array_expr.len |
| 2293 | const index = try addZIRUnOp(mod, &cond_scope.base, cond_src, .deref, index_ptr); | |
| 2294 | const cond = try addZIRBinOp(mod, &cond_scope.base, cond_src, .cmp_lt, index, len); | |
| 2295 | ||
| 2296 | const condbr = try addZIRInstSpecial(mod, &cond_scope.base, for_src, zir.Inst.CondBr, .{ | |
| 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), | |
| 2279 | const index = try cond_scope.addUnNode(.load, index_ptr, for_full.ast.cond_expr); | |
| 2280 | const cond = try cond_scope.addPlNode(.cmp_lt, for_full.ast.cond_expr, zir.Inst.Bin{ | |
| 2281 | .lhs = index, | |
| 2282 | .rhs = len, | |
| 2303 | 2283 | }); |
| 2304 | 2284 | |
| 2305 | // increment index variable | |
| 2306 | const one = try addZIRInstConst(mod, &loop_scope.base, for_src, .{ | |
| 2307 | .ty = Type.initTag(.usize), | |
| 2308 | .val = Value.initTag(.one), | |
| 2309 | }); | |
| 2310 | const index_2 = try addZIRUnOp(mod, &loop_scope.base, cond_src, .deref, index_ptr); | |
| 2311 | const index_plus_one = try addZIRBinOp(mod, &loop_scope.base, for_src, .add, index_2, one); | |
| 2312 | _ = try addZIRBinOp(mod, &loop_scope.base, for_src, .store, index_ptr, index_plus_one); | |
| 2313 | ||
| 2314 | const loop = try scope.arena().create(zir.Inst.Loop); | |
| 2315 | loop.* = .{ | |
| 2316 | .base = .{ | |
| 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}), | |
| 2285 | const condbr_tag: zir.Inst.Tag = if (is_inline) .condbr_inline else .condbr; | |
| 2286 | const condbr = try cond_scope.addCondBr(condbr_tag, node); | |
| 2287 | const block_tag: zir.Inst.Tag = if (is_inline) .block_inline else .block; | |
| 2288 | const cond_block = try loop_scope.addBlock(block_tag, node); | |
| 2289 | try loop_scope.instructions.append(mod.gpa, cond_block); | |
| 2290 | try cond_scope.setBlockBody(cond_block); | |
| 2291 | ||
| 2292 | // Increment the index variable. | |
| 2293 | const index_2 = try loop_scope.addUnNode(.load, index_ptr, for_full.ast.cond_expr); | |
| 2294 | const index_plus_one = try loop_scope.addPlNode(.add, node, zir.Inst.Bin{ | |
| 2295 | .lhs = index_2, | |
| 2296 | .rhs = .one_usize, | |
| 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 | 2304 | loop_scope.continue_block = cond_block; |
| 2332 | 2305 | if (for_full.label_token) |label_token| { |
| 2333 | 2306 | loop_scope.label = @as(?Scope.GenZir.Label, Scope.GenZir.Label{ |
| 2334 | 2307 | .token = label_token, |
| 2335 | .block_inst = for_block, | |
| 2308 | .block_inst = loop_block, | |
| 2336 | 2309 | }); |
| 2337 | 2310 | } |
| 2338 | 2311 | |
| 2339 | // while body | |
| 2340 | const then_src = token_starts[tree.lastToken(for_full.ast.then_expr)]; | |
| 2341 | 2312 | var then_scope: Scope.GenZir = .{ |
| 2342 | 2313 | .parent = &cond_scope.base, |
| 2343 | .decl = cond_scope.decl, | |
| 2344 | .arena = cond_scope.arena, | |
| 2314 | .zir_code = parent_gz.zir_code, | |
| 2345 | 2315 | .force_comptime = cond_scope.force_comptime, |
| 2346 | 2316 | .instructions = .{}, |
| 2347 | 2317 | }; |
| ... | ... | @@ -2375,6 +2345,7 @@ fn forExpr( |
| 2375 | 2345 | .gen_zir = &then_scope, |
| 2376 | 2346 | .name = index_name, |
| 2377 | 2347 | .ptr = index_ptr, |
| 2348 | .src = parent_gz.tokSrcLoc(index_token), | |
| 2378 | 2349 | }; |
| 2379 | 2350 | break :blk &index_scope.base; |
| 2380 | 2351 | }; |
| ... | ... | @@ -2382,34 +2353,36 @@ fn forExpr( |
| 2382 | 2353 | loop_scope.break_count += 1; |
| 2383 | 2354 | const then_result = try expr(mod, then_sub_scope, loop_scope.break_result_loc, for_full.ast.then_expr); |
| 2384 | 2355 | |
| 2385 | // else branch | |
| 2386 | 2356 | var else_scope: Scope.GenZir = .{ |
| 2387 | 2357 | .parent = &cond_scope.base, |
| 2388 | .decl = cond_scope.decl, | |
| 2389 | .arena = cond_scope.arena, | |
| 2358 | .zir_code = parent_gz.zir_code, | |
| 2390 | 2359 | .force_comptime = cond_scope.force_comptime, |
| 2391 | 2360 | .instructions = .{}, |
| 2392 | 2361 | }; |
| 2393 | 2362 | defer else_scope.instructions.deinit(mod.gpa); |
| 2394 | 2363 | |
| 2395 | 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 | 2369 | loop_scope.break_count += 1; |
| 2398 | 2370 | const sub_scope = &else_scope.base; |
| 2399 | 2371 | break :blk .{ |
| 2400 | .src = token_starts[tree.lastToken(else_node)], | |
| 2372 | .src = else_node, | |
| 2401 | 2373 | .result = try expr(mod, sub_scope, loop_scope.break_result_loc, else_node), |
| 2402 | 2374 | }; |
| 2403 | 2375 | } else .{ |
| 2404 | .src = token_starts[tree.lastToken(for_full.ast.then_expr)], | |
| 2405 | .result = null, | |
| 2376 | .src = for_full.ast.then_expr, | |
| 2377 | .result = .none, | |
| 2406 | 2378 | }; |
| 2407 | 2379 | |
| 2408 | 2380 | if (loop_scope.label) |some| { |
| 2409 | 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 | 2386 | return finishThenElseBlock( |
| 2414 | 2387 | mod, |
| 2415 | 2388 | scope, |
| ... | ... | @@ -2420,13 +2393,13 @@ fn forExpr( |
| 2420 | 2393 | &else_scope, |
| 2421 | 2394 | condbr, |
| 2422 | 2395 | cond, |
| 2423 | then_src, | |
| 2396 | for_full.ast.then_expr, | |
| 2424 | 2397 | else_info.src, |
| 2425 | 2398 | then_result, |
| 2426 | 2399 | else_info.result, |
| 2427 | for_block, | |
| 2400 | loop_block, | |
| 2428 | 2401 | cond_block, |
| 2429 | .@"break", | |
| 2402 | break_tag, | |
| 2430 | 2403 | ); |
| 2431 | 2404 | } |
| 2432 | 2405 | |
| ... | ... | @@ -2862,7 +2835,7 @@ fn identifier( |
| 2862 | 2835 | const local_ptr = s.cast(Scope.LocalPtr).?; |
| 2863 | 2836 | if (mem.eql(u8, local_ptr.name, ident_name)) { |
| 2864 | 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 | 2839 | return rvalue(mod, scope, rl, loaded, ident); |
| 2867 | 2840 | } |
| 2868 | 2841 | s = local_ptr.parent; |
src/zir.zig+15-3| ... | ... | @@ -281,7 +281,7 @@ pub const Inst = struct { |
| 281 | 281 | decl_val, |
| 282 | 282 | /// Load the value from a pointer. Assumes `x.*` syntax. |
| 283 | 283 | /// Uses `un_node` field. AST node is the `x.*` syntax. |
| 284 | deref_node, | |
| 284 | load, | |
| 285 | 285 | /// Arithmetic division. Asserts no integer overflow. |
| 286 | 286 | /// Uses the `pl_node` union field. Payload is `Bin`. |
| 287 | 287 | div, |
| ... | ... | @@ -661,7 +661,7 @@ pub const Inst = struct { |
| 661 | 661 | .dbg_stmt_node, |
| 662 | 662 | .decl_ref, |
| 663 | 663 | .decl_val, |
| 664 | .deref_node, | |
| 664 | .load, | |
| 665 | 665 | .div, |
| 666 | 666 | .elem_ptr, |
| 667 | 667 | .elem_val, |
| ... | ... | @@ -841,6 +841,10 @@ pub const Inst = struct { |
| 841 | 841 | bool_true, |
| 842 | 842 | /// `false` |
| 843 | 843 | bool_false, |
| 844 | /// `0` (usize) | |
| 845 | zero_usize, | |
| 846 | /// `1` (usize) | |
| 847 | one_usize, | |
| 844 | 848 | |
| 845 | 849 | _, |
| 846 | 850 | |
| ... | ... | @@ -1016,10 +1020,18 @@ pub const Inst = struct { |
| 1016 | 1020 | .ty = Type.initTag(.comptime_int), |
| 1017 | 1021 | .val = Value.initTag(.zero), |
| 1018 | 1022 | }, |
| 1023 | .zero_usize = .{ | |
| 1024 | .ty = Type.initTag(.usize), | |
| 1025 | .val = Value.initTag(.zero), | |
| 1026 | }, | |
| 1019 | 1027 | .one = .{ |
| 1020 | 1028 | .ty = Type.initTag(.comptime_int), |
| 1021 | 1029 | .val = Value.initTag(.one), |
| 1022 | 1030 | }, |
| 1031 | .one_usize = .{ | |
| 1032 | .ty = Type.initTag(.usize), | |
| 1033 | .val = Value.initTag(.one), | |
| 1034 | }, | |
| 1023 | 1035 | .void_value = .{ |
| 1024 | 1036 | .ty = Type.initTag(.void), |
| 1025 | 1037 | .val = Value.initTag(.void_value), |
| ... | ... | @@ -1377,7 +1389,7 @@ const Writer = struct { |
| 1377 | 1389 | .call_none, |
| 1378 | 1390 | .call_none_chkused, |
| 1379 | 1391 | .compile_error, |
| 1380 | .deref_node, | |
| 1392 | .load, | |
| 1381 | 1393 | .ensure_result_used, |
| 1382 | 1394 | .ensure_result_non_error, |
| 1383 | 1395 | .import, |
test/stage2/test.zig+31-31| ... | ... | @@ -968,37 +968,37 @@ pub fn addCases(ctx: *TestContext) !void { |
| 968 | 968 | ); |
| 969 | 969 | |
| 970 | 970 | // Basic for loop |
| 971 | //case.addCompareOutput( | |
| 972 | // \\export fn _start() noreturn { | |
| 973 | // \\ for ("hello") |_| print(); | |
| 974 | // \\ | |
| 975 | // \\ exit(); | |
| 976 | // \\} | |
| 977 | // \\ | |
| 978 | // \\fn print() void { | |
| 979 | // \\ asm volatile ("syscall" | |
| 980 | // \\ : | |
| 981 | // \\ : [number] "{rax}" (1), | |
| 982 | // \\ [arg1] "{rdi}" (1), | |
| 983 | // \\ [arg2] "{rsi}" (@ptrToInt("hello\n")), | |
| 984 | // \\ [arg3] "{rdx}" (6) | |
| 985 | // \\ : "rcx", "r11", "memory" | |
| 986 | // \\ ); | |
| 987 | // \\ return; | |
| 988 | // \\} | |
| 989 | // \\ | |
| 990 | // \\fn exit() noreturn { | |
| 991 | // \\ asm volatile ("syscall" | |
| 992 | // \\ : | |
| 993 | // \\ : [number] "{rax}" (231), | |
| 994 | // \\ [arg1] "{rdi}" (0) | |
| 995 | // \\ : "rcx", "r11", "memory" | |
| 996 | // \\ ); | |
| 997 | // \\ unreachable; | |
| 998 | // \\} | |
| 999 | //, | |
| 1000 | // "hello\nhello\nhello\nhello\nhello\n", | |
| 1001 | //); | |
| 971 | case.addCompareOutput( | |
| 972 | \\export fn _start() noreturn { | |
| 973 | \\ for ("hello") |_| print(); | |
| 974 | \\ | |
| 975 | \\ exit(); | |
| 976 | \\} | |
| 977 | \\ | |
| 978 | \\fn print() void { | |
| 979 | \\ asm volatile ("syscall" | |
| 980 | \\ : | |
| 981 | \\ : [number] "{rax}" (1), | |
| 982 | \\ [arg1] "{rdi}" (1), | |
| 983 | \\ [arg2] "{rsi}" (@ptrToInt("hello\n")), | |
| 984 | \\ [arg3] "{rdx}" (6) | |
| 985 | \\ : "rcx", "r11", "memory" | |
| 986 | \\ ); | |
| 987 | \\ return; | |
| 988 | \\} | |
| 989 | \\ | |
| 990 | \\fn exit() noreturn { | |
| 991 | \\ asm volatile ("syscall" | |
| 992 | \\ : | |
| 993 | \\ : [number] "{rax}" (231), | |
| 994 | \\ [arg1] "{rdi}" (0) | |
| 995 | \\ : "rcx", "r11", "memory" | |
| 996 | \\ ); | |
| 997 | \\ unreachable; | |
| 998 | \\} | |
| 999 | , | |
| 1000 | "hello\nhello\nhello\nhello\nhello\n", | |
| 1001 | ); | |
| 1002 | 1002 | } |
| 1003 | 1003 | |
| 1004 | 1004 | //{ |