| 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,3 +35,6 @@ Performance optimizations to look into: |
| 35 | * enum literals can use small strings | 35 | * enum literals can use small strings |
| 36 | * string literals can use small strings | 36 | * string literals can use small strings |
| 37 | * don't need the Sema coercion on condbr condition, it's done with result locations | 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,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 | } |
| 581 | 581 | ||
| 582 | fn zirAlloc(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst { | 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,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 | } |
| 1916 | 1916 | ||
| 1917 | fn zirFieldPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst { | 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,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 | } |
| 1944 | 1944 | ||
| 1945 | fn zirFieldPtrNamed(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst { | 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,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 | } |
| 2065 | 2065 | ||
| 2066 | fn zirElemValNode(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst { | 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,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 | } |
| 2080 | 2080 | ||
| 2081 | fn zirElemPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst { | 2081 | fn zirElemPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst { |
| ... | @@ -2183,7 +2183,7 @@ fn zirSwitchBr( | ... | @@ -2183,7 +2183,7 @@ fn zirSwitchBr( |
| 2183 | 2183 | ||
| 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 | else | 2187 | 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 | } |
| 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 | const tracy = trace(@src()); | 2643 | const tracy = trace(@src()); |
| 2644 | defer tracy.end(); | 2644 | defer tracy.end(); |
| 2645 | 2645 | ||
| ... | @@ -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 | } |
| 2652 | 2652 | ||
| 2653 | fn zirAsm( | 2653 | fn 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 | } |
| 2964 | 2964 | ||
| ... | @@ -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 | } |
| 2984 | 2984 | ||
| ... | @@ -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( |
| 3409 | 3409 | ||
| 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 pointer | 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 | 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: |
| 3669 | 3669 | ||
| 3670 | fn analyzeDeclVal(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, decl: *Decl) InnerError!*Inst { | 3670 | fn 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 | } |
| 3674 | 3674 | ||
| 3675 | fn analyzeDeclRef(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, decl: *Decl) InnerError!*Inst { | 3675 | fn 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 | } |
| 3739 | 3739 | ||
| 3740 | fn analyzeDeref( | 3740 | fn 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 |
| 443 | 443 | ||
| 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(); |
| 1397 | 1397 | ||
| 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); |
| 1402 | 1402 | ||
| ... | @@ -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 there | 2149 | // 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 noreturn | 2150 | // 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); |
| 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 | 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 zero | 2252 | // 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); | ||
| 2272 | 2260 | ||
| 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( |
| 2282 | 2269 | ||
| 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); |
| 2291 | 2277 | ||
| 2292 | // check condition i < array_expr.len | 2278 | // 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{ |
| 2295 | 2281 | .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 | }); |
| 2304 | 2284 | ||
| 2305 | // increment index variable | 2285 | 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. |
| 2313 | 2293 | 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 | } |
| 2338 | 2311 | ||
| 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); |
| 2384 | 2355 | ||
| 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); |
| 2394 | 2363 | ||
| 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 | }; |
| 2407 | 2379 | ||
| 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 | } |
| 2432 | 2405 | ||
| ... | @@ -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, | ||
| 844 | 848 | ||
| 845 | _, | 849 | _, |
| 846 | 850 | ||
| ... | @@ -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 | ); |
| 969 | 969 | ||
| 970 | // Basic for loop | 970 | // 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 | } |
| 1003 | 1003 | ||
| 1004 | //{ | 1004 | //{ |