authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-21 20:42:49-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-21 20:42:49-07:00
logea00ddfe3710e386b62849fa4d275b5cbd82e28c
tree8715072bc90faa17b4677a4b6d8bb4bd0d9f7d1b
parent8ee0cbe50a61cdd9495a1276a6adee9955681ecc

AstGen: implement comptime locals


3 files changed, 60 insertions(+), 54 deletions(-)

src/AstGen.zig+10-7
......@@ -1576,8 +1576,10 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: ast.Node.Index) Inner
15761576 .addwrap,
15771577 .alloc,
15781578 .alloc_mut,
1579 .alloc_comptime,
15791580 .alloc_inferred,
15801581 .alloc_inferred_mut,
1582 .alloc_inferred_comptime,
15811583 .array_cat,
15821584 .array_mul,
15831585 .array_type,
......@@ -1665,7 +1667,6 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: ast.Node.Index) Inner
16651667 .ptr_type,
16661668 .ptr_type_simple,
16671669 .enum_literal,
1668 .enum_literal_small,
16691670 .merge_error_sets,
16701671 .error_union_type,
16711672 .bit_not,
......@@ -1901,9 +1902,6 @@ fn varDecl(
19011902) InnerError!*Scope {
19021903 try emitDbgNode(gz, node);
19031904 const astgen = gz.astgen;
1904 if (var_decl.comptime_token) |comptime_token| {
1905 return astgen.failTok(comptime_token, "TODO implement comptime locals", .{});
1906 }
19071905 if (var_decl.ast.align_node != 0) {
19081906 return astgen.failNode(var_decl.ast.align_node, "TODO implement alignment on locals", .{});
19091907 }
......@@ -1961,6 +1959,9 @@ fn varDecl(
19611959
19621960 switch (token_tags[var_decl.ast.mut_token]) {
19631961 .keyword_const => {
1962 if (var_decl.comptime_token) |comptime_token| {
1963 return astgen.failTok(comptime_token, "'comptime const' is redundant; instead wrap the initialization expression with 'comptime'", .{});
1964 }
19641965 // Depending on the type of AST the initialization expression is, we may need an lvalue
19651966 // or an rvalue as a result location. If it is an rvalue, we can use the instruction as
19661967 // the variable, no memory location needed.
......@@ -2062,17 +2063,19 @@ fn varDecl(
20622063 return &sub_scope.base;
20632064 },
20642065 .keyword_var => {
2066 const is_comptime = var_decl.comptime_token != null;
20652067 var resolve_inferred_alloc: Zir.Inst.Ref = .none;
20662068 const var_data: struct {
20672069 result_loc: ResultLoc,
20682070 alloc: Zir.Inst.Ref,
20692071 } = if (var_decl.ast.type_node != 0) a: {
20702072 const type_inst = try typeExpr(gz, scope, var_decl.ast.type_node);
2071
2072 const alloc = try gz.addUnNode(.alloc_mut, type_inst, node);
2073 const tag: Zir.Inst.Tag = if (is_comptime) .alloc_comptime else .alloc_mut;
2074 const alloc = try gz.addUnNode(tag, type_inst, node);
20732075 break :a .{ .alloc = alloc, .result_loc = .{ .ptr = alloc } };
20742076 } else a: {
2075 const alloc = try gz.addNode(.alloc_inferred_mut, node);
2077 const tag: Zir.Inst.Tag = if (is_comptime) .alloc_inferred_comptime else .alloc_inferred_mut;
2078 const alloc = try gz.addNode(tag, node);
20762079 resolve_inferred_alloc = alloc;
20772080 break :a .{ .alloc = alloc, .result_loc = .{ .inferred_ptr = alloc } };
20782081 };
src/Sema.zig+14-14
......@@ -135,7 +135,9 @@ pub fn analyzeBody(
135135 .alloc => try sema.zirAlloc(block, inst),
136136 .alloc_inferred => try sema.zirAllocInferred(block, inst, Type.initTag(.inferred_alloc_const)),
137137 .alloc_inferred_mut => try sema.zirAllocInferred(block, inst, Type.initTag(.inferred_alloc_mut)),
138 .alloc_inferred_comptime => try sema.zirAllocInferredComptime(block, inst),
138139 .alloc_mut => try sema.zirAllocMut(block, inst),
140 .alloc_comptime => try sema.zirAllocComptime(block, inst),
139141 .array_cat => try sema.zirArrayCat(block, inst),
140142 .array_mul => try sema.zirArrayMul(block, inst),
141143 .array_type => try sema.zirArrayType(block, inst),
......@@ -177,7 +179,6 @@ pub fn analyzeBody(
177179 .elem_val_node => try sema.zirElemValNode(block, inst),
178180 .elem_type => try sema.zirElemType(block, inst),
179181 .enum_literal => try sema.zirEnumLiteral(block, inst),
180 .enum_literal_small => try sema.zirEnumLiteralSmall(block, inst),
181182 .enum_to_int => try sema.zirEnumToInt(block, inst),
182183 .int_to_enum => try sema.zirIntToEnum(block, inst),
183184 .err_union_code => try sema.zirErrUnionCode(block, inst),
......@@ -1130,6 +1131,18 @@ fn zirIndexablePtrLen(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) In
11301131 return sema.analyzeLoad(block, src, result_ptr, result_ptr.src);
11311132}
11321133
1134fn zirAllocComptime(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
1135 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
1136 const src = inst_data.src();
1137 return sema.mod.fail(&block.base, src, "TODO implement Sema.zirAllocComptime", .{});
1138}
1139
1140fn zirAllocInferredComptime(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
1141 const src_node = sema.code.instructions.items(.data)[inst].node;
1142 const src: LazySrcLoc = .{ .node_offset = src_node };
1143 return sema.mod.fail(&block.base, src, "TODO implement Sema.zirAllocInferredComptime", .{});
1144}
1145
11331146fn zirAlloc(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
11341147 const tracy = trace(@src());
11351148 defer tracy.end();
......@@ -2334,19 +2347,6 @@ fn zirEnumLiteral(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerE
23342347 });
23352348}
23362349
2337fn zirEnumLiteralSmall(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
2338 const tracy = trace(@src());
2339 defer tracy.end();
2340
2341 const name = sema.code.instructions.items(.data)[inst].small_str.get();
2342 const src: LazySrcLoc = .unneeded;
2343 const duped_name = try sema.arena.dupe(u8, name);
2344 return sema.mod.constInst(sema.arena, src, .{
2345 .ty = Type.initTag(.enum_literal),
2346 .val = try Value.Tag.enum_literal.create(sema.arena, duped_name),
2347 });
2348}
2349
23502350fn zirEnumToInt(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
23512351 const mod = sema.mod;
23522352 const arena = sema.arena;
src/Zir.zig+36-33
......@@ -145,18 +145,6 @@ pub const Inst = struct {
145145 /// Twos complement wrapping integer addition.
146146 /// Uses the `pl_node` union field. Payload is `Bin`.
147147 addwrap,
148 /// Allocates stack local memory.
149 /// Uses the `un_node` union field. The operand is the type of the allocated object.
150 /// The node source location points to a var decl node.
151 /// Indicates the beginning of a new statement in debug info.
152 alloc,
153 /// Same as `alloc` except mutable.
154 alloc_mut,
155 /// Same as `alloc` except the type is inferred.
156 /// Uses the `node` union field.
157 alloc_inferred,
158 /// Same as `alloc_inferred` except mutable.
159 alloc_inferred_mut,
160148 /// Array concatenation. `a ++ b`
161149 /// Uses the `pl_node` union field. Payload is `Bin`.
162150 array_cat,
......@@ -483,12 +471,6 @@ pub const Inst = struct {
483471 /// Create a pointer type which can have a sentinel, alignment, and/or bit range.
484472 /// Uses the `ptr_type` union field.
485473 ptr_type,
486 /// Each `store_to_inferred_ptr` puts the type of the stored value into a set,
487 /// and then `resolve_inferred_alloc` triggers peer type resolution on the set.
488 /// The operand is a `alloc_inferred` or `alloc_inferred_mut` instruction, which
489 /// is the allocation that needs to have its type inferred.
490 /// Uses the `un_node` field. The AST node is the var decl.
491 resolve_inferred_alloc,
492474 /// Slice operation `lhs[rhs..]`. No sentinel and no end offset.
493475 /// Uses the `pl_node` field. AST node is the slice syntax. Payload is `SliceStart`.
494476 slice_start,
......@@ -613,37 +595,40 @@ pub const Inst = struct {
613595 ensure_err_payload_void,
614596 /// An enum literal. Uses the `str_tok` union field.
615597 enum_literal,
616 /// An enum literal 8 or fewer bytes. No source location.
617 /// Uses the `small_str` field.
618 enum_literal_small,
619598 /// A switch expression. Uses the `pl_node` union field.
620599 /// AST node is the switch, payload is `SwitchBlock`.
621600 /// All prongs of target handled.
622601 switch_block,
623602 /// Same as switch_block, except one or more prongs have multiple items.
603 /// Payload is `SwitchBlockMulti`
624604 switch_block_multi,
625605 /// Same as switch_block, except has an else prong.
626606 switch_block_else,
627607 /// Same as switch_block_else, except one or more prongs have multiple items.
608 /// Payload is `SwitchBlockMulti`
628609 switch_block_else_multi,
629610 /// Same as switch_block, except has an underscore prong.
630611 switch_block_under,
631612 /// Same as switch_block, except one or more prongs have multiple items.
613 /// Payload is `SwitchBlockMulti`
632614 switch_block_under_multi,
633615 /// Same as `switch_block` but the target is a pointer to the value being switched on.
634616 switch_block_ref,
635617 /// Same as `switch_block_multi` but the target is a pointer to the value being switched on.
618 /// Payload is `SwitchBlockMulti`
636619 switch_block_ref_multi,
637620 /// Same as `switch_block_else` but the target is a pointer to the value being switched on.
638621 switch_block_ref_else,
639622 /// Same as `switch_block_else_multi` but the target is a pointer to the
640623 /// value being switched on.
624 /// Payload is `SwitchBlockMulti`
641625 switch_block_ref_else_multi,
642626 /// Same as `switch_block_under` but the target is a pointer to the value
643627 /// being switched on.
644628 switch_block_ref_under,
645629 /// Same as `switch_block_under_multi` but the target is a pointer to
646630 /// the value being switched on.
631 /// Payload is `SwitchBlockMulti`
647632 switch_block_ref_under_multi,
648633 /// Produces the capture value for a switch prong.
649634 /// Uses the `switch_capture` field.
......@@ -937,6 +922,32 @@ pub const Inst = struct {
937922 /// Implements the `@cImport` builtin.
938923 /// Uses the `pl_node` union field with payload `Block`.
939924 c_import,
925
926 /// Allocates stack local memory.
927 /// Uses the `un_node` union field. The operand is the type of the allocated object.
928 /// The node source location points to a var decl node.
929 /// Indicates the beginning of a new statement in debug info.
930 alloc,
931 /// Same as `alloc` except mutable.
932 alloc_mut,
933 /// Allocates comptime-mutable memory.
934 /// Uses the `un_node` union field. The operand is the type of the allocated object.
935 /// The node source location points to a var decl node.
936 alloc_comptime,
937 /// Same as `alloc` except the type is inferred.
938 /// Uses the `node` union field.
939 alloc_inferred,
940 /// Same as `alloc_inferred` except mutable.
941 alloc_inferred_mut,
942 /// Same as `alloc_comptime` except the type is inferred.
943 alloc_inferred_comptime,
944 /// Each `store_to_inferred_ptr` puts the type of the stored value into a set,
945 /// and then `resolve_inferred_alloc` triggers peer type resolution on the set.
946 /// The operand is a `alloc_inferred` or `alloc_inferred_mut` instruction, which
947 /// is the allocation that needs to have its type inferred.
948 /// Uses the `un_node` field. The AST node is the var decl.
949 resolve_inferred_alloc,
950
940951 /// The ZIR instruction tag is one of the `Extended` ones.
941952 /// Uses the `extended` union field.
942953 extended,
......@@ -949,8 +960,10 @@ pub const Inst = struct {
949960 .addwrap,
950961 .alloc,
951962 .alloc_mut,
963 .alloc_comptime,
952964 .alloc_inferred,
953965 .alloc_inferred_mut,
966 .alloc_inferred_comptime,
954967 .array_cat,
955968 .array_mul,
956969 .array_type,
......@@ -1066,7 +1079,6 @@ pub const Inst = struct {
10661079 .ptr_type_simple,
10671080 .ensure_err_payload_void,
10681081 .enum_literal,
1069 .enum_literal_small,
10701082 .merge_error_sets,
10711083 .error_union_type,
10721084 .bit_not,
......@@ -2251,6 +2263,7 @@ const Writer = struct {
22512263
22522264 .alloc,
22532265 .alloc_mut,
2266 .alloc_comptime,
22542267 .indexable_ptr_len,
22552268 .bit_not,
22562269 .bool_not,
......@@ -2516,6 +2529,7 @@ const Writer = struct {
25162529 .repeat_inline,
25172530 .alloc_inferred,
25182531 .alloc_inferred_mut,
2532 .alloc_inferred_comptime,
25192533 => try self.writeNode(stream, inst),
25202534
25212535 .error_value,
......@@ -2530,8 +2544,6 @@ const Writer = struct {
25302544
25312545 .@"unreachable" => try self.writeUnreachable(stream, inst),
25322546
2533 .enum_literal_small => try self.writeSmallStr(stream, inst),
2534
25352547 .switch_capture,
25362548 .switch_capture_ref,
25372549 .switch_capture_multi,
......@@ -3442,15 +3454,6 @@ const Writer = struct {
34423454 try self.writeSrc(stream, src);
34433455 }
34443456
3445 fn writeSmallStr(
3446 self: *Writer,
3447 stream: anytype,
3448 inst: Inst.Index,
3449 ) (@TypeOf(stream).Error || error{OutOfMemory})!void {
3450 const str = self.code.instructions.items(.data)[inst].small_str.get();
3451 try stream.print("\"{}\")", .{std.zig.fmtEscapes(str)});
3452 }
3453
34543457 fn writeSwitchCapture(self: *Writer, stream: anytype, inst: Inst.Index) !void {
34553458 const inst_data = self.code.instructions.items(.data)[inst].switch_capture;
34563459 try self.writeInstIndex(stream, inst_data.switch_inst);