mirror of
https://github.com/ziglang/zig.git
synced 2025-12-30 18:13:19 +00:00
AstGen: implement comptime locals
This commit is contained in:
parent
8ee0cbe50a
commit
ea00ddfe37
@ -1576,8 +1576,10 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: ast.Node.Index) Inner
|
||||
.addwrap,
|
||||
.alloc,
|
||||
.alloc_mut,
|
||||
.alloc_comptime,
|
||||
.alloc_inferred,
|
||||
.alloc_inferred_mut,
|
||||
.alloc_inferred_comptime,
|
||||
.array_cat,
|
||||
.array_mul,
|
||||
.array_type,
|
||||
@ -1665,7 +1667,6 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: ast.Node.Index) Inner
|
||||
.ptr_type,
|
||||
.ptr_type_simple,
|
||||
.enum_literal,
|
||||
.enum_literal_small,
|
||||
.merge_error_sets,
|
||||
.error_union_type,
|
||||
.bit_not,
|
||||
@ -1901,9 +1902,6 @@ fn varDecl(
|
||||
) InnerError!*Scope {
|
||||
try emitDbgNode(gz, node);
|
||||
const astgen = gz.astgen;
|
||||
if (var_decl.comptime_token) |comptime_token| {
|
||||
return astgen.failTok(comptime_token, "TODO implement comptime locals", .{});
|
||||
}
|
||||
if (var_decl.ast.align_node != 0) {
|
||||
return astgen.failNode(var_decl.ast.align_node, "TODO implement alignment on locals", .{});
|
||||
}
|
||||
@ -1961,6 +1959,9 @@ fn varDecl(
|
||||
|
||||
switch (token_tags[var_decl.ast.mut_token]) {
|
||||
.keyword_const => {
|
||||
if (var_decl.comptime_token) |comptime_token| {
|
||||
return astgen.failTok(comptime_token, "'comptime const' is redundant; instead wrap the initialization expression with 'comptime'", .{});
|
||||
}
|
||||
// Depending on the type of AST the initialization expression is, we may need an lvalue
|
||||
// or an rvalue as a result location. If it is an rvalue, we can use the instruction as
|
||||
// the variable, no memory location needed.
|
||||
@ -2062,17 +2063,19 @@ fn varDecl(
|
||||
return &sub_scope.base;
|
||||
},
|
||||
.keyword_var => {
|
||||
const is_comptime = var_decl.comptime_token != null;
|
||||
var resolve_inferred_alloc: Zir.Inst.Ref = .none;
|
||||
const var_data: struct {
|
||||
result_loc: ResultLoc,
|
||||
alloc: Zir.Inst.Ref,
|
||||
} = if (var_decl.ast.type_node != 0) a: {
|
||||
const type_inst = try typeExpr(gz, scope, var_decl.ast.type_node);
|
||||
|
||||
const alloc = try gz.addUnNode(.alloc_mut, type_inst, node);
|
||||
const tag: Zir.Inst.Tag = if (is_comptime) .alloc_comptime else .alloc_mut;
|
||||
const alloc = try gz.addUnNode(tag, type_inst, node);
|
||||
break :a .{ .alloc = alloc, .result_loc = .{ .ptr = alloc } };
|
||||
} else a: {
|
||||
const alloc = try gz.addNode(.alloc_inferred_mut, node);
|
||||
const tag: Zir.Inst.Tag = if (is_comptime) .alloc_inferred_comptime else .alloc_inferred_mut;
|
||||
const alloc = try gz.addNode(tag, node);
|
||||
resolve_inferred_alloc = alloc;
|
||||
break :a .{ .alloc = alloc, .result_loc = .{ .inferred_ptr = alloc } };
|
||||
};
|
||||
|
||||
28
src/Sema.zig
28
src/Sema.zig
@ -135,7 +135,9 @@ pub fn analyzeBody(
|
||||
.alloc => try sema.zirAlloc(block, inst),
|
||||
.alloc_inferred => try sema.zirAllocInferred(block, inst, Type.initTag(.inferred_alloc_const)),
|
||||
.alloc_inferred_mut => try sema.zirAllocInferred(block, inst, Type.initTag(.inferred_alloc_mut)),
|
||||
.alloc_inferred_comptime => try sema.zirAllocInferredComptime(block, inst),
|
||||
.alloc_mut => try sema.zirAllocMut(block, inst),
|
||||
.alloc_comptime => try sema.zirAllocComptime(block, inst),
|
||||
.array_cat => try sema.zirArrayCat(block, inst),
|
||||
.array_mul => try sema.zirArrayMul(block, inst),
|
||||
.array_type => try sema.zirArrayType(block, inst),
|
||||
@ -177,7 +179,6 @@ pub fn analyzeBody(
|
||||
.elem_val_node => try sema.zirElemValNode(block, inst),
|
||||
.elem_type => try sema.zirElemType(block, inst),
|
||||
.enum_literal => try sema.zirEnumLiteral(block, inst),
|
||||
.enum_literal_small => try sema.zirEnumLiteralSmall(block, inst),
|
||||
.enum_to_int => try sema.zirEnumToInt(block, inst),
|
||||
.int_to_enum => try sema.zirIntToEnum(block, inst),
|
||||
.err_union_code => try sema.zirErrUnionCode(block, inst),
|
||||
@ -1130,6 +1131,18 @@ fn zirIndexablePtrLen(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) In
|
||||
return sema.analyzeLoad(block, src, result_ptr, result_ptr.src);
|
||||
}
|
||||
|
||||
fn zirAllocComptime(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
|
||||
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
|
||||
const src = inst_data.src();
|
||||
return sema.mod.fail(&block.base, src, "TODO implement Sema.zirAllocComptime", .{});
|
||||
}
|
||||
|
||||
fn zirAllocInferredComptime(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
|
||||
const src_node = sema.code.instructions.items(.data)[inst].node;
|
||||
const src: LazySrcLoc = .{ .node_offset = src_node };
|
||||
return sema.mod.fail(&block.base, src, "TODO implement Sema.zirAllocInferredComptime", .{});
|
||||
}
|
||||
|
||||
fn zirAlloc(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
@ -2334,19 +2347,6 @@ fn zirEnumLiteral(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerE
|
||||
});
|
||||
}
|
||||
|
||||
fn zirEnumLiteralSmall(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
const name = sema.code.instructions.items(.data)[inst].small_str.get();
|
||||
const src: LazySrcLoc = .unneeded;
|
||||
const duped_name = try sema.arena.dupe(u8, name);
|
||||
return sema.mod.constInst(sema.arena, src, .{
|
||||
.ty = Type.initTag(.enum_literal),
|
||||
.val = try Value.Tag.enum_literal.create(sema.arena, duped_name),
|
||||
});
|
||||
}
|
||||
|
||||
fn zirEnumToInt(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
|
||||
const mod = sema.mod;
|
||||
const arena = sema.arena;
|
||||
|
||||
69
src/Zir.zig
69
src/Zir.zig
@ -145,18 +145,6 @@ pub const Inst = struct {
|
||||
/// Twos complement wrapping integer addition.
|
||||
/// Uses the `pl_node` union field. Payload is `Bin`.
|
||||
addwrap,
|
||||
/// Allocates stack local memory.
|
||||
/// Uses the `un_node` union field. The operand is the type of the allocated object.
|
||||
/// The node source location points to a var decl node.
|
||||
/// Indicates the beginning of a new statement in debug info.
|
||||
alloc,
|
||||
/// Same as `alloc` except mutable.
|
||||
alloc_mut,
|
||||
/// Same as `alloc` except the type is inferred.
|
||||
/// Uses the `node` union field.
|
||||
alloc_inferred,
|
||||
/// Same as `alloc_inferred` except mutable.
|
||||
alloc_inferred_mut,
|
||||
/// Array concatenation. `a ++ b`
|
||||
/// Uses the `pl_node` union field. Payload is `Bin`.
|
||||
array_cat,
|
||||
@ -483,12 +471,6 @@ pub const Inst = struct {
|
||||
/// Create a pointer type which can have a sentinel, alignment, and/or bit range.
|
||||
/// Uses the `ptr_type` union field.
|
||||
ptr_type,
|
||||
/// Each `store_to_inferred_ptr` puts the type of the stored value into a set,
|
||||
/// and then `resolve_inferred_alloc` triggers peer type resolution on the set.
|
||||
/// The operand is a `alloc_inferred` or `alloc_inferred_mut` instruction, which
|
||||
/// is the allocation that needs to have its type inferred.
|
||||
/// Uses the `un_node` field. The AST node is the var decl.
|
||||
resolve_inferred_alloc,
|
||||
/// Slice operation `lhs[rhs..]`. No sentinel and no end offset.
|
||||
/// Uses the `pl_node` field. AST node is the slice syntax. Payload is `SliceStart`.
|
||||
slice_start,
|
||||
@ -613,37 +595,40 @@ pub const Inst = struct {
|
||||
ensure_err_payload_void,
|
||||
/// An enum literal. Uses the `str_tok` union field.
|
||||
enum_literal,
|
||||
/// An enum literal 8 or fewer bytes. No source location.
|
||||
/// Uses the `small_str` field.
|
||||
enum_literal_small,
|
||||
/// A switch expression. Uses the `pl_node` union field.
|
||||
/// AST node is the switch, payload is `SwitchBlock`.
|
||||
/// All prongs of target handled.
|
||||
switch_block,
|
||||
/// Same as switch_block, except one or more prongs have multiple items.
|
||||
/// Payload is `SwitchBlockMulti`
|
||||
switch_block_multi,
|
||||
/// Same as switch_block, except has an else prong.
|
||||
switch_block_else,
|
||||
/// Same as switch_block_else, except one or more prongs have multiple items.
|
||||
/// Payload is `SwitchBlockMulti`
|
||||
switch_block_else_multi,
|
||||
/// Same as switch_block, except has an underscore prong.
|
||||
switch_block_under,
|
||||
/// Same as switch_block, except one or more prongs have multiple items.
|
||||
/// Payload is `SwitchBlockMulti`
|
||||
switch_block_under_multi,
|
||||
/// Same as `switch_block` but the target is a pointer to the value being switched on.
|
||||
switch_block_ref,
|
||||
/// Same as `switch_block_multi` but the target is a pointer to the value being switched on.
|
||||
/// Payload is `SwitchBlockMulti`
|
||||
switch_block_ref_multi,
|
||||
/// Same as `switch_block_else` but the target is a pointer to the value being switched on.
|
||||
switch_block_ref_else,
|
||||
/// Same as `switch_block_else_multi` but the target is a pointer to the
|
||||
/// value being switched on.
|
||||
/// Payload is `SwitchBlockMulti`
|
||||
switch_block_ref_else_multi,
|
||||
/// Same as `switch_block_under` but the target is a pointer to the value
|
||||
/// being switched on.
|
||||
switch_block_ref_under,
|
||||
/// Same as `switch_block_under_multi` but the target is a pointer to
|
||||
/// the value being switched on.
|
||||
/// Payload is `SwitchBlockMulti`
|
||||
switch_block_ref_under_multi,
|
||||
/// Produces the capture value for a switch prong.
|
||||
/// Uses the `switch_capture` field.
|
||||
@ -937,6 +922,32 @@ pub const Inst = struct {
|
||||
/// Implements the `@cImport` builtin.
|
||||
/// Uses the `pl_node` union field with payload `Block`.
|
||||
c_import,
|
||||
|
||||
/// Allocates stack local memory.
|
||||
/// Uses the `un_node` union field. The operand is the type of the allocated object.
|
||||
/// The node source location points to a var decl node.
|
||||
/// Indicates the beginning of a new statement in debug info.
|
||||
alloc,
|
||||
/// Same as `alloc` except mutable.
|
||||
alloc_mut,
|
||||
/// Allocates comptime-mutable memory.
|
||||
/// Uses the `un_node` union field. The operand is the type of the allocated object.
|
||||
/// The node source location points to a var decl node.
|
||||
alloc_comptime,
|
||||
/// Same as `alloc` except the type is inferred.
|
||||
/// Uses the `node` union field.
|
||||
alloc_inferred,
|
||||
/// Same as `alloc_inferred` except mutable.
|
||||
alloc_inferred_mut,
|
||||
/// Same as `alloc_comptime` except the type is inferred.
|
||||
alloc_inferred_comptime,
|
||||
/// Each `store_to_inferred_ptr` puts the type of the stored value into a set,
|
||||
/// and then `resolve_inferred_alloc` triggers peer type resolution on the set.
|
||||
/// The operand is a `alloc_inferred` or `alloc_inferred_mut` instruction, which
|
||||
/// is the allocation that needs to have its type inferred.
|
||||
/// Uses the `un_node` field. The AST node is the var decl.
|
||||
resolve_inferred_alloc,
|
||||
|
||||
/// The ZIR instruction tag is one of the `Extended` ones.
|
||||
/// Uses the `extended` union field.
|
||||
extended,
|
||||
@ -949,8 +960,10 @@ pub const Inst = struct {
|
||||
.addwrap,
|
||||
.alloc,
|
||||
.alloc_mut,
|
||||
.alloc_comptime,
|
||||
.alloc_inferred,
|
||||
.alloc_inferred_mut,
|
||||
.alloc_inferred_comptime,
|
||||
.array_cat,
|
||||
.array_mul,
|
||||
.array_type,
|
||||
@ -1066,7 +1079,6 @@ pub const Inst = struct {
|
||||
.ptr_type_simple,
|
||||
.ensure_err_payload_void,
|
||||
.enum_literal,
|
||||
.enum_literal_small,
|
||||
.merge_error_sets,
|
||||
.error_union_type,
|
||||
.bit_not,
|
||||
@ -2251,6 +2263,7 @@ const Writer = struct {
|
||||
|
||||
.alloc,
|
||||
.alloc_mut,
|
||||
.alloc_comptime,
|
||||
.indexable_ptr_len,
|
||||
.bit_not,
|
||||
.bool_not,
|
||||
@ -2516,6 +2529,7 @@ const Writer = struct {
|
||||
.repeat_inline,
|
||||
.alloc_inferred,
|
||||
.alloc_inferred_mut,
|
||||
.alloc_inferred_comptime,
|
||||
=> try self.writeNode(stream, inst),
|
||||
|
||||
.error_value,
|
||||
@ -2530,8 +2544,6 @@ const Writer = struct {
|
||||
|
||||
.@"unreachable" => try self.writeUnreachable(stream, inst),
|
||||
|
||||
.enum_literal_small => try self.writeSmallStr(stream, inst),
|
||||
|
||||
.switch_capture,
|
||||
.switch_capture_ref,
|
||||
.switch_capture_multi,
|
||||
@ -3442,15 +3454,6 @@ const Writer = struct {
|
||||
try self.writeSrc(stream, src);
|
||||
}
|
||||
|
||||
fn writeSmallStr(
|
||||
self: *Writer,
|
||||
stream: anytype,
|
||||
inst: Inst.Index,
|
||||
) (@TypeOf(stream).Error || error{OutOfMemory})!void {
|
||||
const str = self.code.instructions.items(.data)[inst].small_str.get();
|
||||
try stream.print("\"{}\")", .{std.zig.fmtEscapes(str)});
|
||||
}
|
||||
|
||||
fn writeSwitchCapture(self: *Writer, stream: anytype, inst: Inst.Index) !void {
|
||||
const inst_data = self.code.instructions.items(.data)[inst].switch_capture;
|
||||
try self.writeInstIndex(stream, inst_data.switch_inst);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user