| author | |
| committer | |
| log | 7efd7bc3b8cc403814c0aa62be0a17ff25b33902 |
| tree | 7b92414b05bfc0e66bdc8aff4f3a68abc9a88ee7 |
| parent | ca6951ff7959b88573bfec7c7bf0465209f3263f |
5 files changed, 181 insertions(+), 6 deletions(-)
src/AstGen.zig+1-1| ... | @@ -2357,7 +2357,7 @@ fn varDecl( | ... | @@ -2357,7 +2357,7 @@ fn varDecl( |
| 2357 | return &sub_scope.base; | 2357 | return &sub_scope.base; |
| 2358 | }, | 2358 | }, |
| 2359 | .keyword_var => { | 2359 | .keyword_var => { |
| 2360 | const is_comptime = var_decl.comptime_token != null; | 2360 | const is_comptime = var_decl.comptime_token != null or gz.force_comptime; |
| 2361 | var resolve_inferred_alloc: Zir.Inst.Ref = .none; | 2361 | var resolve_inferred_alloc: Zir.Inst.Ref = .none; |
| 2362 | const var_data: struct { | 2362 | const var_data: struct { |
| 2363 | result_loc: ResultLoc, | 2363 | result_loc: ResultLoc, |
src/Module.zig+10| ... | @@ -1139,6 +1139,13 @@ pub const Scope = struct { | ... | @@ -1139,6 +1139,13 @@ pub const Scope = struct { |
| 1139 | instructions: ArrayListUnmanaged(*ir.Inst), | 1139 | instructions: ArrayListUnmanaged(*ir.Inst), |
| 1140 | label: ?*Label = null, | 1140 | label: ?*Label = null, |
| 1141 | inlining: ?*Inlining, | 1141 | inlining: ?*Inlining, |
| 1142 | /// If runtime_index is not 0 then one of these is guaranteed to be non null. | ||
| 1143 | runtime_cond: ?LazySrcLoc = null, | ||
| 1144 | runtime_loop: ?LazySrcLoc = null, | ||
| 1145 | /// Non zero if a non-inline loop or a runtime conditional have been encountered. | ||
| 1146 | /// Stores to to comptime variables are only allowed when var.runtime_index <= runtime_index. | ||
| 1147 | runtime_index: u32 = 0, | ||
| 1148 | |||
| 1142 | is_comptime: bool, | 1149 | is_comptime: bool, |
| 1143 | 1150 | ||
| 1144 | /// This `Block` maps a block ZIR instruction to the corresponding | 1151 | /// This `Block` maps a block ZIR instruction to the corresponding |
| ... | @@ -1182,6 +1189,9 @@ pub const Scope = struct { | ... | @@ -1182,6 +1189,9 @@ pub const Scope = struct { |
| 1182 | .label = null, | 1189 | .label = null, |
| 1183 | .inlining = parent.inlining, | 1190 | .inlining = parent.inlining, |
| 1184 | .is_comptime = parent.is_comptime, | 1191 | .is_comptime = parent.is_comptime, |
| 1192 | .runtime_cond = parent.runtime_cond, | ||
| 1193 | .runtime_loop = parent.runtime_loop, | ||
| 1194 | .runtime_index = parent.runtime_index, | ||
| 1185 | }; | 1195 | }; |
| 1186 | } | 1196 | } |
| 1187 | 1197 |
src/Sema.zig+62-5| ... | @@ -509,7 +509,7 @@ pub fn analyzeBody( | ... | @@ -509,7 +509,7 @@ pub fn analyzeBody( |
| 509 | }; | 509 | }; |
| 510 | if (air_inst.ty.isNoReturn()) | 510 | if (air_inst.ty.isNoReturn()) |
| 511 | return always_noreturn; | 511 | return always_noreturn; |
| 512 | try map.putNoClobber(sema.gpa, inst, air_inst); | 512 | try map.put(sema.gpa, inst, air_inst); |
| 513 | } | 513 | } |
| 514 | } | 514 | } |
| 515 | 515 | ||
| ... | @@ -1238,9 +1238,26 @@ fn zirAllocExtended( | ... | @@ -1238,9 +1238,26 @@ fn zirAllocExtended( |
| 1238 | } | 1238 | } |
| 1239 | 1239 | ||
| 1240 | fn zirAllocComptime(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst { | 1240 | fn zirAllocComptime(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst { |
| 1241 | const tracy = trace(@src()); | ||
| 1242 | defer tracy.end(); | ||
| 1243 | |||
| 1241 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; | 1244 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 1242 | const src = inst_data.src(); | 1245 | const src = inst_data.src(); |
| 1243 | return sema.mod.fail(&block.base, src, "TODO implement Sema.zirAllocComptime", .{}); | 1246 | const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = inst_data.src_node }; |
| 1247 | const var_type = try sema.resolveType(block, ty_src, inst_data.operand); | ||
| 1248 | const ptr_type = try sema.mod.simplePtrType(sema.arena, var_type, true, .One); | ||
| 1249 | |||
| 1250 | const val_payload = try sema.arena.create(Value.Payload.ComptimeAlloc); | ||
| 1251 | val_payload.* = .{ | ||
| 1252 | .data = .{ | ||
| 1253 | .runtime_index = block.runtime_index, | ||
| 1254 | .val = undefined, // astgen guarantees there will be a store before the first load | ||
| 1255 | }, | ||
| 1256 | }; | ||
| 1257 | return sema.mod.constInst(sema.arena, src, .{ | ||
| 1258 | .ty = ptr_type, | ||
| 1259 | .val = Value.initPayload(&val_payload.base), | ||
| 1260 | }); | ||
| 1244 | } | 1261 | } |
| 1245 | 1262 | ||
| 1246 | fn zirAllocInferredComptime(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst { | 1263 | fn zirAllocInferredComptime(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst { |
| ... | @@ -1742,6 +1759,9 @@ fn zirLoop(sema: *Sema, parent_block: *Scope.Block, inst: Zir.Inst.Index) InnerE | ... | @@ -1742,6 +1759,9 @@ fn zirLoop(sema: *Sema, parent_block: *Scope.Block, inst: Zir.Inst.Index) InnerE |
| 1742 | }; | 1759 | }; |
| 1743 | var child_block = parent_block.makeSubBlock(); | 1760 | var child_block = parent_block.makeSubBlock(); |
| 1744 | child_block.label = &label; | 1761 | child_block.label = &label; |
| 1762 | child_block.runtime_cond = null; | ||
| 1763 | child_block.runtime_loop = src; | ||
| 1764 | child_block.runtime_index += 1; | ||
| 1745 | const merges = &child_block.label.?.merges; | 1765 | const merges = &child_block.label.?.merges; |
| 1746 | 1766 | ||
| 1747 | defer child_block.instructions.deinit(sema.gpa); | 1767 | defer child_block.instructions.deinit(sema.gpa); |
| ... | @@ -4066,6 +4086,9 @@ fn analyzeSwitch( | ... | @@ -4066,6 +4086,9 @@ fn analyzeSwitch( |
| 4066 | const cases = try sema.arena.alloc(Inst.SwitchBr.Case, scalar_cases_len); | 4086 | const cases = try sema.arena.alloc(Inst.SwitchBr.Case, scalar_cases_len); |
| 4067 | 4087 | ||
| 4068 | var case_block = child_block.makeSubBlock(); | 4088 | var case_block = child_block.makeSubBlock(); |
| 4089 | case_block.runtime_loop = null; | ||
| 4090 | case_block.runtime_cond = operand.src; | ||
| 4091 | case_block.runtime_index += 1; | ||
| 4069 | defer case_block.instructions.deinit(gpa); | 4092 | defer case_block.instructions.deinit(gpa); |
| 4070 | 4093 | ||
| 4071 | var extra_index: usize = special.end; | 4094 | var extra_index: usize = special.end; |
| ... | @@ -4584,14 +4607,14 @@ fn zirArithmetic(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerEr | ... | @@ -4584,14 +4607,14 @@ fn zirArithmetic(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerEr |
| 4584 | 4607 | ||
| 4585 | const tag_override = block.sema.code.instructions.items(.tag)[inst]; | 4608 | const tag_override = block.sema.code.instructions.items(.tag)[inst]; |
| 4586 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 4609 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 4587 | const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node }; | 4610 | sema.src = .{ .node_offset_bin_op = inst_data.src_node }; |
| 4588 | const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; | 4611 | const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; |
| 4589 | const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node }; | 4612 | const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node }; |
| 4590 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; | 4613 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 4591 | const lhs = try sema.resolveInst(extra.lhs); | 4614 | const lhs = try sema.resolveInst(extra.lhs); |
| 4592 | const rhs = try sema.resolveInst(extra.rhs); | 4615 | const rhs = try sema.resolveInst(extra.rhs); |
| 4593 | 4616 | ||
| 4594 | return sema.analyzeArithmetic(block, tag_override, lhs, rhs, src, lhs_src, rhs_src); | 4617 | return sema.analyzeArithmetic(block, tag_override, lhs, rhs, sema.src, lhs_src, rhs_src); |
| 4595 | } | 4618 | } |
| 4596 | 4619 | ||
| 4597 | fn zirOverflowArithmetic( | 4620 | fn zirOverflowArithmetic( |
| ... | @@ -5150,6 +5173,9 @@ fn zirBoolBr( | ... | @@ -5150,6 +5173,9 @@ fn zirBoolBr( |
| 5150 | }; | 5173 | }; |
| 5151 | 5174 | ||
| 5152 | var child_block = parent_block.makeSubBlock(); | 5175 | var child_block = parent_block.makeSubBlock(); |
| 5176 | child_block.runtime_loop = null; | ||
| 5177 | child_block.runtime_cond = lhs.src; | ||
| 5178 | child_block.runtime_index += 1; | ||
| 5153 | defer child_block.instructions.deinit(sema.gpa); | 5179 | defer child_block.instructions.deinit(sema.gpa); |
| 5154 | 5180 | ||
| 5155 | var then_block = child_block.makeSubBlock(); | 5181 | var then_block = child_block.makeSubBlock(); |
| ... | @@ -5258,6 +5284,9 @@ fn zirCondbr( | ... | @@ -5258,6 +5284,9 @@ fn zirCondbr( |
| 5258 | } | 5284 | } |
| 5259 | 5285 | ||
| 5260 | var sub_block = parent_block.makeSubBlock(); | 5286 | var sub_block = parent_block.makeSubBlock(); |
| 5287 | sub_block.runtime_loop = null; | ||
| 5288 | sub_block.runtime_cond = cond.src; | ||
| 5289 | sub_block.runtime_index += 1; | ||
| 5261 | defer sub_block.instructions.deinit(sema.gpa); | 5290 | defer sub_block.instructions.deinit(sema.gpa); |
| 5262 | 5291 | ||
| 5263 | _ = try sema.analyzeBody(&sub_block, then_body); | 5292 | _ = try sema.analyzeBody(&sub_block, then_body); |
| ... | @@ -6753,7 +6782,35 @@ fn storePtr( | ... | @@ -6753,7 +6782,35 @@ fn storePtr( |
| 6753 | if ((try sema.typeHasOnePossibleValue(block, src, elem_ty)) != null) | 6782 | if ((try sema.typeHasOnePossibleValue(block, src, elem_ty)) != null) |
| 6754 | return; | 6783 | return; |
| 6755 | 6784 | ||
| 6756 | // TODO handle comptime pointer writes | 6785 | if (try sema.resolvePossiblyUndefinedValue(block, src, ptr)) |ptr_val| { |
| 6786 | const const_val = (try sema.resolvePossiblyUndefinedValue(block, src, value)) orelse | ||
| 6787 | return sema.mod.fail(&block.base, src, "cannot store runtime value in compile time variable", .{}); | ||
| 6788 | |||
| 6789 | const comptime_alloc = ptr_val.castTag(.comptime_alloc).?; | ||
| 6790 | if (comptime_alloc.data.runtime_index < block.runtime_index) { | ||
| 6791 | if (block.runtime_cond) |cond_src| { | ||
| 6792 | const msg = msg: { | ||
| 6793 | const msg = try sema.mod.errMsg(&block.base, src, "store to comptime variable depends on runtime condition", .{}); | ||
| 6794 | errdefer msg.destroy(sema.gpa); | ||
| 6795 | try sema.mod.errNote(&block.base, cond_src, msg, "runtime condition here", .{}); | ||
| 6796 | break :msg msg; | ||
| 6797 | }; | ||
| 6798 | return sema.mod.failWithOwnedErrorMsg(&block.base, msg); | ||
| 6799 | } | ||
| 6800 | if (block.runtime_loop) |loop_src| { | ||
| 6801 | const msg = msg: { | ||
| 6802 | const msg = try sema.mod.errMsg(&block.base, src, "cannot store to comptime variable in non-inline loop", .{}); | ||
| 6803 | errdefer msg.destroy(sema.gpa); | ||
| 6804 | try sema.mod.errNote(&block.base, loop_src, msg, "non-inline loop here", .{}); | ||
| 6805 | break :msg msg; | ||
| 6806 | }; | ||
| 6807 | return sema.mod.failWithOwnedErrorMsg(&block.base, msg); | ||
| 6808 | } | ||
| 6809 | unreachable; | ||
| 6810 | } | ||
| 6811 | comptime_alloc.data.val = const_val; | ||
| 6812 | return; | ||
| 6813 | } | ||
| 6757 | // TODO handle if the element type requires comptime | 6814 | // TODO handle if the element type requires comptime |
| 6758 | 6815 | ||
| 6759 | try sema.requireRuntimeBlock(block, src); | 6816 | try sema.requireRuntimeBlock(block, src); |
src/value.zig+26| ... | @@ -101,6 +101,8 @@ pub const Value = extern union { | ... | @@ -101,6 +101,8 @@ pub const Value = extern union { |
| 101 | variable, | 101 | variable, |
| 102 | /// Represents a pointer to another immutable value. | 102 | /// Represents a pointer to another immutable value. |
| 103 | ref_val, | 103 | ref_val, |
| 104 | /// Represents a comptime variables storage. | ||
| 105 | comptime_alloc, | ||
| 104 | /// Represents a pointer to a decl, not the value of the decl. | 106 | /// Represents a pointer to a decl, not the value of the decl. |
| 105 | decl_ref, | 107 | decl_ref, |
| 106 | elem_ptr, | 108 | elem_ptr, |
| ... | @@ -223,6 +225,7 @@ pub const Value = extern union { | ... | @@ -223,6 +225,7 @@ pub const Value = extern union { |
| 223 | .int_i64 => Payload.I64, | 225 | .int_i64 => Payload.I64, |
| 224 | .function => Payload.Function, | 226 | .function => Payload.Function, |
| 225 | .variable => Payload.Variable, | 227 | .variable => Payload.Variable, |
| 228 | .comptime_alloc => Payload.ComptimeAlloc, | ||
| 226 | .elem_ptr => Payload.ElemPtr, | 229 | .elem_ptr => Payload.ElemPtr, |
| 227 | .field_ptr => Payload.FieldPtr, | 230 | .field_ptr => Payload.FieldPtr, |
| 228 | .float_16 => Payload.Float_16, | 231 | .float_16 => Payload.Float_16, |
| ... | @@ -403,6 +406,7 @@ pub const Value = extern union { | ... | @@ -403,6 +406,7 @@ pub const Value = extern union { |
| 403 | }; | 406 | }; |
| 404 | return Value{ .ptr_otherwise = &new_payload.base }; | 407 | return Value{ .ptr_otherwise = &new_payload.base }; |
| 405 | }, | 408 | }, |
| 409 | .comptime_alloc => return self.copyPayloadShallow(allocator, Payload.ComptimeAlloc), | ||
| 406 | .decl_ref => return self.copyPayloadShallow(allocator, Payload.Decl), | 410 | .decl_ref => return self.copyPayloadShallow(allocator, Payload.Decl), |
| 407 | .elem_ptr => { | 411 | .elem_ptr => { |
| 408 | const payload = self.castTag(.elem_ptr).?; | 412 | const payload = self.castTag(.elem_ptr).?; |
| ... | @@ -577,6 +581,11 @@ pub const Value = extern union { | ... | @@ -577,6 +581,11 @@ pub const Value = extern union { |
| 577 | try out_stream.writeAll("&const "); | 581 | try out_stream.writeAll("&const "); |
| 578 | val = ref_val; | 582 | val = ref_val; |
| 579 | }, | 583 | }, |
| 584 | .comptime_alloc => { | ||
| 585 | const ref_val = val.castTag(.comptime_alloc).?.data.val; | ||
| 586 | try out_stream.writeAll("&"); | ||
| 587 | val = ref_val; | ||
| 588 | }, | ||
| 580 | .decl_ref => return out_stream.writeAll("(decl ref)"), | 589 | .decl_ref => return out_stream.writeAll("(decl ref)"), |
| 581 | .elem_ptr => { | 590 | .elem_ptr => { |
| 582 | const elem_ptr = val.castTag(.elem_ptr).?.data; | 591 | const elem_ptr = val.castTag(.elem_ptr).?.data; |
| ... | @@ -713,6 +722,7 @@ pub const Value = extern union { | ... | @@ -713,6 +722,7 @@ pub const Value = extern union { |
| 713 | .extern_fn, | 722 | .extern_fn, |
| 714 | .variable, | 723 | .variable, |
| 715 | .ref_val, | 724 | .ref_val, |
| 725 | .comptime_alloc, | ||
| 716 | .decl_ref, | 726 | .decl_ref, |
| 717 | .elem_ptr, | 727 | .elem_ptr, |
| 718 | .field_ptr, | 728 | .field_ptr, |
| ... | @@ -1186,6 +1196,10 @@ pub const Value = extern union { | ... | @@ -1186,6 +1196,10 @@ pub const Value = extern union { |
| 1186 | const payload = self.castTag(.ref_val).?; | 1196 | const payload = self.castTag(.ref_val).?; |
| 1187 | std.hash.autoHash(&hasher, payload.data.hash()); | 1197 | std.hash.autoHash(&hasher, payload.data.hash()); |
| 1188 | }, | 1198 | }, |
| 1199 | .comptime_alloc => { | ||
| 1200 | const payload = self.castTag(.comptime_alloc).?; | ||
| 1201 | std.hash.autoHash(&hasher, payload.data.val.hash()); | ||
| 1202 | }, | ||
| 1189 | .int_big_positive, .int_big_negative => { | 1203 | .int_big_positive, .int_big_negative => { |
| 1190 | var space: BigIntSpace = undefined; | 1204 | var space: BigIntSpace = undefined; |
| 1191 | const big = self.toBigInt(&space); | 1205 | const big = self.toBigInt(&space); |
| ... | @@ -1277,6 +1291,7 @@ pub const Value = extern union { | ... | @@ -1277,6 +1291,7 @@ pub const Value = extern union { |
| 1277 | /// Returns error.AnalysisFail if the pointer points to a Decl that failed semantic analysis. | 1291 | /// Returns error.AnalysisFail if the pointer points to a Decl that failed semantic analysis. |
| 1278 | pub fn pointerDeref(self: Value, allocator: *Allocator) error{ AnalysisFail, OutOfMemory }!Value { | 1292 | pub fn pointerDeref(self: Value, allocator: *Allocator) error{ AnalysisFail, OutOfMemory }!Value { |
| 1279 | return switch (self.tag()) { | 1293 | return switch (self.tag()) { |
| 1294 | .comptime_alloc => self.castTag(.comptime_alloc).?.data.val, | ||
| 1280 | .ref_val => self.castTag(.ref_val).?.data, | 1295 | .ref_val => self.castTag(.ref_val).?.data, |
| 1281 | .decl_ref => self.castTag(.decl_ref).?.data.value(), | 1296 | .decl_ref => self.castTag(.decl_ref).?.data.value(), |
| 1282 | .elem_ptr => { | 1297 | .elem_ptr => { |
| ... | @@ -1462,6 +1477,7 @@ pub const Value = extern union { | ... | @@ -1462,6 +1477,7 @@ pub const Value = extern union { |
| 1462 | .int_big_positive, | 1477 | .int_big_positive, |
| 1463 | .int_big_negative, | 1478 | .int_big_negative, |
| 1464 | .ref_val, | 1479 | .ref_val, |
| 1480 | .comptime_alloc, | ||
| 1465 | .decl_ref, | 1481 | .decl_ref, |
| 1466 | .elem_ptr, | 1482 | .elem_ptr, |
| 1467 | .field_ptr, | 1483 | .field_ptr, |
| ... | @@ -1542,6 +1558,16 @@ pub const Value = extern union { | ... | @@ -1542,6 +1558,16 @@ pub const Value = extern union { |
| 1542 | data: Value, | 1558 | data: Value, |
| 1543 | }; | 1559 | }; |
| 1544 | 1560 | ||
| 1561 | pub const ComptimeAlloc = struct { | ||
| 1562 | pub const base_tag = Tag.comptime_alloc; | ||
| 1563 | |||
| 1564 | base: Payload = Payload{ .tag = base_tag }, | ||
| 1565 | data: struct { | ||
| 1566 | val: Value, | ||
| 1567 | runtime_index: u32, | ||
| 1568 | }, | ||
| 1569 | }; | ||
| 1570 | |||
| 1545 | pub const ElemPtr = struct { | 1571 | pub const ElemPtr = struct { |
| 1546 | pub const base_tag = Tag.elem_ptr; | 1572 | pub const base_tag = Tag.elem_ptr; |
| 1547 | 1573 |
test/stage2/test.zig+82| ... | @@ -1420,4 +1420,86 @@ pub fn addCases(ctx: *TestContext) !void { | ... | @@ -1420,4 +1420,86 @@ pub fn addCases(ctx: *TestContext) !void { |
| 1420 | \\} | 1420 | \\} |
| 1421 | , &[_][]const u8{":4:27: error: expected type, found comptime_int"}); | 1421 | , &[_][]const u8{":4:27: error: expected type, found comptime_int"}); |
| 1422 | } | 1422 | } |
| 1423 | { | ||
| 1424 | var case = ctx.exe("comptime var", linux_x64); | ||
| 1425 | |||
| 1426 | case.addError( | ||
| 1427 | \\pub fn main() void { | ||
| 1428 | \\ var a: u32 = 0; | ||
| 1429 | \\ comptime var b: u32 = 0; | ||
| 1430 | \\ if (a == 0) b = 3; | ||
| 1431 | \\} | ||
| 1432 | , &.{ | ||
| 1433 | ":4:21: error: store to comptime variable depends on runtime condition", | ||
| 1434 | ":4:11: note: runtime condition here", | ||
| 1435 | }); | ||
| 1436 | |||
| 1437 | case.addError( | ||
| 1438 | \\pub fn main() void { | ||
| 1439 | \\ var a: u32 = 0; | ||
| 1440 | \\ comptime var b: u32 = 0; | ||
| 1441 | \\ switch (a) { | ||
| 1442 | \\ 0 => {}, | ||
| 1443 | \\ else => b = 3, | ||
| 1444 | \\ } | ||
| 1445 | \\} | ||
| 1446 | , &.{ | ||
| 1447 | ":6:21: error: store to comptime variable depends on runtime condition", | ||
| 1448 | ":4:13: note: runtime condition here", | ||
| 1449 | }); | ||
| 1450 | |||
| 1451 | case.addCompareOutput( | ||
| 1452 | \\pub fn main() void { | ||
| 1453 | \\ comptime var len: u32 = 5; | ||
| 1454 | \\ print(len); | ||
| 1455 | \\ len += 9; | ||
| 1456 | \\ print(len); | ||
| 1457 | \\} | ||
| 1458 | \\ | ||
| 1459 | \\fn print(len: usize) void { | ||
| 1460 | \\ asm volatile ("syscall" | ||
| 1461 | \\ : | ||
| 1462 | \\ : [number] "{rax}" (1), | ||
| 1463 | \\ [arg1] "{rdi}" (1), | ||
| 1464 | \\ [arg2] "{rsi}" (@ptrToInt("Hello, World!\n")), | ||
| 1465 | \\ [arg3] "{rdx}" (len) | ||
| 1466 | \\ : "rcx", "r11", "memory" | ||
| 1467 | \\ ); | ||
| 1468 | \\ return; | ||
| 1469 | \\} | ||
| 1470 | , "HelloHello, World!\n"); | ||
| 1471 | |||
| 1472 | case.addError( | ||
| 1473 | \\comptime { | ||
| 1474 | \\ var x: i32 = 1; | ||
| 1475 | \\ x += 1; | ||
| 1476 | \\ if (x != 1) unreachable; | ||
| 1477 | \\} | ||
| 1478 | , &.{":4:17: error: unable to resolve comptime value"}); | ||
| 1479 | |||
| 1480 | case.addError( | ||
| 1481 | \\pub fn main() void { | ||
| 1482 | \\ comptime var i: u64 = 0; | ||
| 1483 | \\ while (i < 5) : (i += 1) {} | ||
| 1484 | \\} | ||
| 1485 | , &.{ | ||
| 1486 | ":3:24: error: cannot store to comptime variable in non-inline loop", | ||
| 1487 | ":3:5: note: non-inline loop here", | ||
| 1488 | }); | ||
| 1489 | |||
| 1490 | case.addCompareOutput( | ||
| 1491 | \\pub fn main() void { | ||
| 1492 | \\ var a: u32 = 0; | ||
| 1493 | \\ if (a == 0) { | ||
| 1494 | \\ comptime var b: u32 = 0; | ||
| 1495 | \\ b = 1; | ||
| 1496 | \\ } | ||
| 1497 | \\} | ||
| 1498 | \\comptime { | ||
| 1499 | \\ var x: i32 = 1; | ||
| 1500 | \\ x += 1; | ||
| 1501 | \\ if (x != 2) unreachable; | ||
| 1502 | \\} | ||
| 1503 | , ""); | ||
| 1504 | } | ||
| 1423 | } | 1505 | } |