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...@@ -1576,8 +1576,10 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: ast.Node.Index) Inner
1576 .addwrap,1576 .addwrap,
1577 .alloc,1577 .alloc,
1578 .alloc_mut,1578 .alloc_mut,
1579 .alloc_comptime,
1579 .alloc_inferred,1580 .alloc_inferred,
1580 .alloc_inferred_mut,1581 .alloc_inferred_mut,
1582 .alloc_inferred_comptime,
1581 .array_cat,1583 .array_cat,
1582 .array_mul,1584 .array_mul,
1583 .array_type,1585 .array_type,
...@@ -1665,7 +1667,6 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: ast.Node.Index) Inner...@@ -1665,7 +1667,6 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: ast.Node.Index) Inner
1665 .ptr_type,1667 .ptr_type,
1666 .ptr_type_simple,1668 .ptr_type_simple,
1667 .enum_literal,1669 .enum_literal,
1668 .enum_literal_small,
1669 .merge_error_sets,1670 .merge_error_sets,
1670 .error_union_type,1671 .error_union_type,
1671 .bit_not,1672 .bit_not,
...@@ -1901,9 +1902,6 @@ fn varDecl(...@@ -1901,9 +1902,6 @@ fn varDecl(
1901) InnerError!*Scope {1902) InnerError!*Scope {
1902 try emitDbgNode(gz, node);1903 try emitDbgNode(gz, node);
1903 const astgen = gz.astgen;1904 const astgen = gz.astgen;
1904 if (var_decl.comptime_token) |comptime_token| {
1905 return astgen.failTok(comptime_token, "TODO implement comptime locals", .{});
1906 }
1907 if (var_decl.ast.align_node != 0) {1905 if (var_decl.ast.align_node != 0) {
1908 return astgen.failNode(var_decl.ast.align_node, "TODO implement alignment on locals", .{});1906 return astgen.failNode(var_decl.ast.align_node, "TODO implement alignment on locals", .{});
1909 }1907 }
...@@ -1961,6 +1959,9 @@ fn varDecl(...@@ -1961,6 +1959,9 @@ fn varDecl(
19611959
1962 switch (token_tags[var_decl.ast.mut_token]) {1960 switch (token_tags[var_decl.ast.mut_token]) {
1963 .keyword_const => {1961 .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 }
1964 // Depending on the type of AST the initialization expression is, we may need an lvalue1965 // Depending on the type of AST the initialization expression is, we may need an lvalue
1965 // or an rvalue as a result location. If it is an rvalue, we can use the instruction as1966 // or an rvalue as a result location. If it is an rvalue, we can use the instruction as
1966 // the variable, no memory location needed.1967 // the variable, no memory location needed.
...@@ -2062,17 +2063,19 @@ fn varDecl(...@@ -2062,17 +2063,19 @@ fn varDecl(
2062 return &sub_scope.base;2063 return &sub_scope.base;
2063 },2064 },
2064 .keyword_var => {2065 .keyword_var => {
2066 const is_comptime = var_decl.comptime_token != null;
2065 var resolve_inferred_alloc: Zir.Inst.Ref = .none;2067 var resolve_inferred_alloc: Zir.Inst.Ref = .none;
2066 const var_data: struct {2068 const var_data: struct {
2067 result_loc: ResultLoc,2069 result_loc: ResultLoc,
2068 alloc: Zir.Inst.Ref,2070 alloc: Zir.Inst.Ref,
2069 } = if (var_decl.ast.type_node != 0) a: {2071 } = if (var_decl.ast.type_node != 0) a: {
2070 const type_inst = try typeExpr(gz, scope, var_decl.ast.type_node);2072 const type_inst = try typeExpr(gz, scope, var_decl.ast.type_node);
20712073 const tag: Zir.Inst.Tag = if (is_comptime) .alloc_comptime else .alloc_mut;
2072 const alloc = try gz.addUnNode(.alloc_mut, type_inst, node);2074 const alloc = try gz.addUnNode(tag, type_inst, node);
2073 break :a .{ .alloc = alloc, .result_loc = .{ .ptr = alloc } };2075 break :a .{ .alloc = alloc, .result_loc = .{ .ptr = alloc } };
2074 } else a: {2076 } 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);
2076 resolve_inferred_alloc = alloc;2079 resolve_inferred_alloc = alloc;
2077 break :a .{ .alloc = alloc, .result_loc = .{ .inferred_ptr = alloc } };2080 break :a .{ .alloc = alloc, .result_loc = .{ .inferred_ptr = alloc } };
2078 };2081 };
src/Sema.zig+14-14
...@@ -135,7 +135,9 @@ pub fn analyzeBody(...@@ -135,7 +135,9 @@ pub fn analyzeBody(
135 .alloc => try sema.zirAlloc(block, inst),135 .alloc => try sema.zirAlloc(block, inst),
136 .alloc_inferred => try sema.zirAllocInferred(block, inst, Type.initTag(.inferred_alloc_const)),136 .alloc_inferred => try sema.zirAllocInferred(block, inst, Type.initTag(.inferred_alloc_const)),
137 .alloc_inferred_mut => try sema.zirAllocInferred(block, inst, Type.initTag(.inferred_alloc_mut)),137 .alloc_inferred_mut => try sema.zirAllocInferred(block, inst, Type.initTag(.inferred_alloc_mut)),
138 .alloc_inferred_comptime => try sema.zirAllocInferredComptime(block, inst),
138 .alloc_mut => try sema.zirAllocMut(block, inst),139 .alloc_mut => try sema.zirAllocMut(block, inst),
140 .alloc_comptime => try sema.zirAllocComptime(block, inst),
139 .array_cat => try sema.zirArrayCat(block, inst),141 .array_cat => try sema.zirArrayCat(block, inst),
140 .array_mul => try sema.zirArrayMul(block, inst),142 .array_mul => try sema.zirArrayMul(block, inst),
141 .array_type => try sema.zirArrayType(block, inst),143 .array_type => try sema.zirArrayType(block, inst),
...@@ -177,7 +179,6 @@ pub fn analyzeBody(...@@ -177,7 +179,6 @@ pub fn analyzeBody(
177 .elem_val_node => try sema.zirElemValNode(block, inst),179 .elem_val_node => try sema.zirElemValNode(block, inst),
178 .elem_type => try sema.zirElemType(block, inst),180 .elem_type => try sema.zirElemType(block, inst),
179 .enum_literal => try sema.zirEnumLiteral(block, inst),181 .enum_literal => try sema.zirEnumLiteral(block, inst),
180 .enum_literal_small => try sema.zirEnumLiteralSmall(block, inst),
181 .enum_to_int => try sema.zirEnumToInt(block, inst),182 .enum_to_int => try sema.zirEnumToInt(block, inst),
182 .int_to_enum => try sema.zirIntToEnum(block, inst),183 .int_to_enum => try sema.zirIntToEnum(block, inst),
183 .err_union_code => try sema.zirErrUnionCode(block, inst),184 .err_union_code => try sema.zirErrUnionCode(block, inst),
...@@ -1130,6 +1131,18 @@ fn zirIndexablePtrLen(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) In...@@ -1130,6 +1131,18 @@ fn zirIndexablePtrLen(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) In
1130 return sema.analyzeLoad(block, src, result_ptr, result_ptr.src);1131 return sema.analyzeLoad(block, src, result_ptr, result_ptr.src);
1131}1132}
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
1133fn zirAlloc(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {1146fn zirAlloc(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
1134 const tracy = trace(@src());1147 const tracy = trace(@src());
1135 defer tracy.end();1148 defer tracy.end();
...@@ -2334,19 +2347,6 @@ fn zirEnumLiteral(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerE...@@ -2334,19 +2347,6 @@ fn zirEnumLiteral(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerE
2334 });2347 });
2335}2348}
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
2350fn zirEnumToInt(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {2350fn zirEnumToInt(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
2351 const mod = sema.mod;2351 const mod = sema.mod;
2352 const arena = sema.arena;2352 const arena = sema.arena;
src/Zir.zig+36-33
...@@ -145,18 +145,6 @@ pub const Inst = struct {...@@ -145,18 +145,6 @@ pub const Inst = struct {
145 /// Twos complement wrapping integer addition.145 /// Twos complement wrapping integer addition.
146 /// Uses the `pl_node` union field. Payload is `Bin`.146 /// Uses the `pl_node` union field. Payload is `Bin`.
147 addwrap,147 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,
160 /// Array concatenation. `a ++ b`148 /// Array concatenation. `a ++ b`
161 /// Uses the `pl_node` union field. Payload is `Bin`.149 /// Uses the `pl_node` union field. Payload is `Bin`.
162 array_cat,150 array_cat,
...@@ -483,12 +471,6 @@ pub const Inst = struct {...@@ -483,12 +471,6 @@ pub const Inst = struct {
483 /// Create a pointer type which can have a sentinel, alignment, and/or bit range.471 /// Create a pointer type which can have a sentinel, alignment, and/or bit range.
484 /// Uses the `ptr_type` union field.472 /// Uses the `ptr_type` union field.
485 ptr_type,473 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,
492 /// Slice operation `lhs[rhs..]`. No sentinel and no end offset.474 /// Slice operation `lhs[rhs..]`. No sentinel and no end offset.
493 /// Uses the `pl_node` field. AST node is the slice syntax. Payload is `SliceStart`.475 /// Uses the `pl_node` field. AST node is the slice syntax. Payload is `SliceStart`.
494 slice_start,476 slice_start,
...@@ -613,37 +595,40 @@ pub const Inst = struct {...@@ -613,37 +595,40 @@ pub const Inst = struct {
613 ensure_err_payload_void,595 ensure_err_payload_void,
614 /// An enum literal. Uses the `str_tok` union field.596 /// An enum literal. Uses the `str_tok` union field.
615 enum_literal,597 enum_literal,
616 /// An enum literal 8 or fewer bytes. No source location.
617 /// Uses the `small_str` field.
618 enum_literal_small,
619 /// A switch expression. Uses the `pl_node` union field.598 /// A switch expression. Uses the `pl_node` union field.
620 /// AST node is the switch, payload is `SwitchBlock`.599 /// AST node is the switch, payload is `SwitchBlock`.
621 /// All prongs of target handled.600 /// All prongs of target handled.
622 switch_block,601 switch_block,
623 /// Same as switch_block, except one or more prongs have multiple items.602 /// Same as switch_block, except one or more prongs have multiple items.
603 /// Payload is `SwitchBlockMulti`
624 switch_block_multi,604 switch_block_multi,
625 /// Same as switch_block, except has an else prong.605 /// Same as switch_block, except has an else prong.
626 switch_block_else,606 switch_block_else,
627 /// Same as switch_block_else, except one or more prongs have multiple items.607 /// Same as switch_block_else, except one or more prongs have multiple items.
608 /// Payload is `SwitchBlockMulti`
628 switch_block_else_multi,609 switch_block_else_multi,
629 /// Same as switch_block, except has an underscore prong.610 /// Same as switch_block, except has an underscore prong.
630 switch_block_under,611 switch_block_under,
631 /// Same as switch_block, except one or more prongs have multiple items.612 /// Same as switch_block, except one or more prongs have multiple items.
613 /// Payload is `SwitchBlockMulti`
632 switch_block_under_multi,614 switch_block_under_multi,
633 /// Same as `switch_block` but the target is a pointer to the value being switched on.615 /// Same as `switch_block` but the target is a pointer to the value being switched on.
634 switch_block_ref,616 switch_block_ref,
635 /// Same as `switch_block_multi` but the target is a pointer to the value being switched on.617 /// Same as `switch_block_multi` but the target is a pointer to the value being switched on.
618 /// Payload is `SwitchBlockMulti`
636 switch_block_ref_multi,619 switch_block_ref_multi,
637 /// Same as `switch_block_else` but the target is a pointer to the value being switched on.620 /// Same as `switch_block_else` but the target is a pointer to the value being switched on.
638 switch_block_ref_else,621 switch_block_ref_else,
639 /// Same as `switch_block_else_multi` but the target is a pointer to the622 /// Same as `switch_block_else_multi` but the target is a pointer to the
640 /// value being switched on.623 /// value being switched on.
624 /// Payload is `SwitchBlockMulti`
641 switch_block_ref_else_multi,625 switch_block_ref_else_multi,
642 /// Same as `switch_block_under` but the target is a pointer to the value626 /// Same as `switch_block_under` but the target is a pointer to the value
643 /// being switched on.627 /// being switched on.
644 switch_block_ref_under,628 switch_block_ref_under,
645 /// Same as `switch_block_under_multi` but the target is a pointer to629 /// Same as `switch_block_under_multi` but the target is a pointer to
646 /// the value being switched on.630 /// the value being switched on.
631 /// Payload is `SwitchBlockMulti`
647 switch_block_ref_under_multi,632 switch_block_ref_under_multi,
648 /// Produces the capture value for a switch prong.633 /// Produces the capture value for a switch prong.
649 /// Uses the `switch_capture` field.634 /// Uses the `switch_capture` field.
...@@ -937,6 +922,32 @@ pub const Inst = struct {...@@ -937,6 +922,32 @@ pub const Inst = struct {
937 /// Implements the `@cImport` builtin.922 /// Implements the `@cImport` builtin.
938 /// Uses the `pl_node` union field with payload `Block`.923 /// Uses the `pl_node` union field with payload `Block`.
939 c_import,924 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
940 /// The ZIR instruction tag is one of the `Extended` ones.951 /// The ZIR instruction tag is one of the `Extended` ones.
941 /// Uses the `extended` union field.952 /// Uses the `extended` union field.
942 extended,953 extended,
...@@ -949,8 +960,10 @@ pub const Inst = struct {...@@ -949,8 +960,10 @@ pub const Inst = struct {
949 .addwrap,960 .addwrap,
950 .alloc,961 .alloc,
951 .alloc_mut,962 .alloc_mut,
963 .alloc_comptime,
952 .alloc_inferred,964 .alloc_inferred,
953 .alloc_inferred_mut,965 .alloc_inferred_mut,
966 .alloc_inferred_comptime,
954 .array_cat,967 .array_cat,
955 .array_mul,968 .array_mul,
956 .array_type,969 .array_type,
...@@ -1066,7 +1079,6 @@ pub const Inst = struct {...@@ -1066,7 +1079,6 @@ pub const Inst = struct {
1066 .ptr_type_simple,1079 .ptr_type_simple,
1067 .ensure_err_payload_void,1080 .ensure_err_payload_void,
1068 .enum_literal,1081 .enum_literal,
1069 .enum_literal_small,
1070 .merge_error_sets,1082 .merge_error_sets,
1071 .error_union_type,1083 .error_union_type,
1072 .bit_not,1084 .bit_not,
...@@ -2251,6 +2263,7 @@ const Writer = struct {...@@ -2251,6 +2263,7 @@ const Writer = struct {
22512263
2252 .alloc,2264 .alloc,
2253 .alloc_mut,2265 .alloc_mut,
2266 .alloc_comptime,
2254 .indexable_ptr_len,2267 .indexable_ptr_len,
2255 .bit_not,2268 .bit_not,
2256 .bool_not,2269 .bool_not,
...@@ -2516,6 +2529,7 @@ const Writer = struct {...@@ -2516,6 +2529,7 @@ const Writer = struct {
2516 .repeat_inline,2529 .repeat_inline,
2517 .alloc_inferred,2530 .alloc_inferred,
2518 .alloc_inferred_mut,2531 .alloc_inferred_mut,
2532 .alloc_inferred_comptime,
2519 => try self.writeNode(stream, inst),2533 => try self.writeNode(stream, inst),
25202534
2521 .error_value,2535 .error_value,
...@@ -2530,8 +2544,6 @@ const Writer = struct {...@@ -2530,8 +2544,6 @@ const Writer = struct {
25302544
2531 .@"unreachable" => try self.writeUnreachable(stream, inst),2545 .@"unreachable" => try self.writeUnreachable(stream, inst),
25322546
2533 .enum_literal_small => try self.writeSmallStr(stream, inst),
2534
2535 .switch_capture,2547 .switch_capture,
2536 .switch_capture_ref,2548 .switch_capture_ref,
2537 .switch_capture_multi,2549 .switch_capture_multi,
...@@ -3442,15 +3454,6 @@ const Writer = struct {...@@ -3442,15 +3454,6 @@ const Writer = struct {
3442 try self.writeSrc(stream, src);3454 try self.writeSrc(stream, src);
3443 }3455 }
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
3454 fn writeSwitchCapture(self: *Writer, stream: anytype, inst: Inst.Index) !void {3457 fn writeSwitchCapture(self: *Writer, stream: anytype, inst: Inst.Index) !void {
3455 const inst_data = self.code.instructions.items(.data)[inst].switch_capture;3458 const inst_data = self.code.instructions.items(.data)[inst].switch_capture;
3456 try self.writeInstIndex(stream, inst_data.switch_inst);3459 try self.writeInstIndex(stream, inst_data.switch_inst);