mirror of
https://codeberg.org/ziglang/zig.git
synced 2026-05-08 10:48:04 +03:00
stage2: astgen: fix most of the remaining compile errors
more progress on converting astgen to the new AST memory layout. only a few code paths left to update.
This commit is contained in:
+10
-30
@@ -1754,25 +1754,20 @@ pub const Tree = struct {
|
||||
const token_tags = tree.tokens.items(.tag);
|
||||
// TODO: looks like stage1 isn't quite smart enough to handle enum
|
||||
// literals in some places here
|
||||
const Kind = full.PtrType.Kind;
|
||||
const kind: Kind = switch (token_tags[info.main_token]) {
|
||||
const Size = std.builtin.TypeInfo.Pointer.Size;
|
||||
const size: Size = switch (token_tags[info.main_token]) {
|
||||
.asterisk,
|
||||
.asterisk_asterisk,
|
||||
=> switch (token_tags[info.main_token + 1]) {
|
||||
.r_bracket => .many,
|
||||
.colon => .sentinel,
|
||||
.identifier => if (token_tags[info.main_token - 1] == .l_bracket) Kind.c else .one,
|
||||
else => .one,
|
||||
},
|
||||
.l_bracket => switch (token_tags[info.main_token + 1]) {
|
||||
.r_bracket => Kind.slice,
|
||||
.colon => .slice_sentinel,
|
||||
else => unreachable,
|
||||
.r_bracket, .colon => .Many,
|
||||
.identifier => if (token_tags[info.main_token - 1] == .l_bracket) Size.C else .One,
|
||||
else => .One,
|
||||
},
|
||||
.l_bracket => Size.Slice,
|
||||
else => unreachable,
|
||||
};
|
||||
var result: full.PtrType = .{
|
||||
.kind = kind,
|
||||
.size = size,
|
||||
.allowzero_token = null,
|
||||
.const_token = null,
|
||||
.volatile_token = null,
|
||||
@@ -1782,13 +1777,7 @@ pub const Tree = struct {
|
||||
// here while looking for modifiers as that could result in false
|
||||
// positives. Therefore, start after a sentinel if there is one and
|
||||
// skip over any align node and bit range nodes.
|
||||
var i = if (kind == .sentinel or kind == .slice_sentinel) blk: {
|
||||
assert(info.sentinel != 0);
|
||||
break :blk tree.lastToken(info.sentinel) + 1;
|
||||
} else blk: {
|
||||
assert(info.sentinel == 0);
|
||||
break :blk info.main_token;
|
||||
};
|
||||
var i = if (info.sentinel != 0) tree.lastToken(info.sentinel) + 1 else info.main_token;
|
||||
const end = tree.firstToken(info.child_type);
|
||||
while (i < end) : (i += 1) {
|
||||
switch (token_tags[i]) {
|
||||
@@ -2115,7 +2104,7 @@ pub const full = struct {
|
||||
.comptime_noalias = comptime_noalias,
|
||||
.name_token = name_token,
|
||||
.anytype_ellipsis3 = it.tok_i - 1,
|
||||
.type_expr = param_type,
|
||||
.type_expr = 0,
|
||||
};
|
||||
}
|
||||
it.tok_flag = false;
|
||||
@@ -2166,21 +2155,12 @@ pub const full = struct {
|
||||
};
|
||||
|
||||
pub const PtrType = struct {
|
||||
kind: Kind,
|
||||
size: std.builtin.TypeInfo.Pointer.Size,
|
||||
allowzero_token: ?TokenIndex,
|
||||
const_token: ?TokenIndex,
|
||||
volatile_token: ?TokenIndex,
|
||||
ast: Ast,
|
||||
|
||||
pub const Kind = enum {
|
||||
one,
|
||||
many,
|
||||
sentinel,
|
||||
c,
|
||||
slice,
|
||||
slice_sentinel,
|
||||
};
|
||||
|
||||
pub const Ast = struct {
|
||||
main_token: TokenIndex,
|
||||
align_node: Node.Index,
|
||||
|
||||
+25
-23
@@ -677,8 +677,8 @@ fn renderPtrType(
|
||||
ptr_type: ast.full.PtrType,
|
||||
space: Space,
|
||||
) Error!void {
|
||||
switch (ptr_type.kind) {
|
||||
.one => {
|
||||
switch (ptr_type.size) {
|
||||
.One => {
|
||||
// Since ** tokens exist and the same token is shared by two
|
||||
// nested pointer types, we check to see if we are the parent
|
||||
// in such a relationship. If so, skip rendering anything for
|
||||
@@ -691,33 +691,35 @@ fn renderPtrType(
|
||||
}
|
||||
try renderToken(ais, tree, ptr_type.ast.main_token, .none); // asterisk
|
||||
},
|
||||
.many => {
|
||||
try renderToken(ais, tree, ptr_type.ast.main_token - 1, .none); // lbracket
|
||||
try renderToken(ais, tree, ptr_type.ast.main_token, .none); // asterisk
|
||||
try renderToken(ais, tree, ptr_type.ast.main_token + 1, .none); // rbracket
|
||||
.Many => {
|
||||
if (ptr_type.ast.sentinel == 0) {
|
||||
try renderToken(ais, tree, ptr_type.ast.main_token - 1, .none); // lbracket
|
||||
try renderToken(ais, tree, ptr_type.ast.main_token, .none); // asterisk
|
||||
try renderToken(ais, tree, ptr_type.ast.main_token + 1, .none); // rbracket
|
||||
} else {
|
||||
try renderToken(ais, tree, ptr_type.ast.main_token - 1, .none); // lbracket
|
||||
try renderToken(ais, tree, ptr_type.ast.main_token, .none); // asterisk
|
||||
try renderToken(ais, tree, ptr_type.ast.main_token + 1, .none); // colon
|
||||
try renderExpression(ais, tree, ptr_type.ast.sentinel, .none);
|
||||
try renderToken(ais, tree, tree.lastToken(ptr_type.ast.sentinel) + 1, .none); // rbracket
|
||||
}
|
||||
},
|
||||
.sentinel => {
|
||||
try renderToken(ais, tree, ptr_type.ast.main_token - 1, .none); // lbracket
|
||||
try renderToken(ais, tree, ptr_type.ast.main_token, .none); // asterisk
|
||||
try renderToken(ais, tree, ptr_type.ast.main_token + 1, .none); // colon
|
||||
try renderExpression(ais, tree, ptr_type.ast.sentinel, .none);
|
||||
try renderToken(ais, tree, tree.lastToken(ptr_type.ast.sentinel) + 1, .none); // rbracket
|
||||
},
|
||||
.c => {
|
||||
.C => {
|
||||
try renderToken(ais, tree, ptr_type.ast.main_token - 1, .none); // lbracket
|
||||
try renderToken(ais, tree, ptr_type.ast.main_token, .none); // asterisk
|
||||
try renderToken(ais, tree, ptr_type.ast.main_token + 1, .none); // c
|
||||
try renderToken(ais, tree, ptr_type.ast.main_token + 2, .none); // rbracket
|
||||
},
|
||||
.slice => {
|
||||
try renderToken(ais, tree, ptr_type.ast.main_token, .none); // lbracket
|
||||
try renderToken(ais, tree, ptr_type.ast.main_token + 1, .none); // rbracket
|
||||
},
|
||||
.slice_sentinel => {
|
||||
try renderToken(ais, tree, ptr_type.ast.main_token, .none); // lbracket
|
||||
try renderToken(ais, tree, ptr_type.ast.main_token + 1, .none); // colon
|
||||
try renderExpression(ais, tree, ptr_type.ast.sentinel, .none);
|
||||
try renderToken(ais, tree, tree.lastToken(ptr_type.ast.sentinel) + 1, .none); // rbracket
|
||||
.Slice => {
|
||||
if (ptr_type.ast.sentinel == 0) {
|
||||
try renderToken(ais, tree, ptr_type.ast.main_token, .none); // lbracket
|
||||
try renderToken(ais, tree, ptr_type.ast.main_token + 1, .none); // rbracket
|
||||
} else {
|
||||
try renderToken(ais, tree, ptr_type.ast.main_token, .none); // lbracket
|
||||
try renderToken(ais, tree, ptr_type.ast.main_token + 1, .none); // colon
|
||||
try renderExpression(ais, tree, ptr_type.ast.sentinel, .none);
|
||||
try renderToken(ais, tree, tree.lastToken(ptr_type.ast.sentinel) + 1, .none); // rbracket
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
+523
-520
@@ -115,727 +115,730 @@ allows_lvalue: bool = false,
|
||||
/// of parameters.
|
||||
param_count: ?u8,
|
||||
|
||||
pub const list = std.ComptimeStringMap(@This(), .{
|
||||
.{
|
||||
"@addWithOverflow",
|
||||
pub const list = list: {
|
||||
@setEvalBranchQuota(3000);
|
||||
break :list std.ComptimeStringMap(@This(), .{
|
||||
.{
|
||||
.tag = .add_with_overflow,
|
||||
.param_count = 4,
|
||||
"@addWithOverflow",
|
||||
.{
|
||||
.tag = .add_with_overflow,
|
||||
.param_count = 4,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@alignCast",
|
||||
.{
|
||||
.tag = align_cast,
|
||||
.param_count = 1,
|
||||
"@alignCast",
|
||||
.{
|
||||
.tag = .align_cast,
|
||||
.param_count = 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@alignOf",
|
||||
.{
|
||||
.tag = .align_of,
|
||||
.param_count = 1,
|
||||
"@alignOf",
|
||||
.{
|
||||
.tag = .align_of,
|
||||
.param_count = 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@as",
|
||||
.{
|
||||
.tag = .as,
|
||||
.needs_mem_loc = true,
|
||||
.param_count = 2,
|
||||
"@as",
|
||||
.{
|
||||
.tag = .as,
|
||||
.needs_mem_loc = true,
|
||||
.param_count = 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@asyncCall",
|
||||
.{
|
||||
.tag = .async_call,
|
||||
.param_count = null,
|
||||
"@asyncCall",
|
||||
.{
|
||||
.tag = .async_call,
|
||||
.param_count = null,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@atomicLoad",
|
||||
.{
|
||||
.tag = .atomic_load,
|
||||
.param_count = 3,
|
||||
"@atomicLoad",
|
||||
.{
|
||||
.tag = .atomic_load,
|
||||
.param_count = 3,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@atomicRmw",
|
||||
.{
|
||||
.tag = .atomic_rmw,
|
||||
.param_count = 5,
|
||||
"@atomicRmw",
|
||||
.{
|
||||
.tag = .atomic_rmw,
|
||||
.param_count = 5,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@atomicStore",
|
||||
.{
|
||||
.tag = .atomic_store,
|
||||
.param_count = 4,
|
||||
"@atomicStore",
|
||||
.{
|
||||
.tag = .atomic_store,
|
||||
.param_count = 4,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@bitCast",
|
||||
.{
|
||||
.tag = .bit_cast,
|
||||
.needs_mem_loc = true,
|
||||
.param_count = 2,
|
||||
"@bitCast",
|
||||
.{
|
||||
.tag = .bit_cast,
|
||||
.needs_mem_loc = true,
|
||||
.param_count = 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@bitOffsetOf",
|
||||
.{
|
||||
.tag = .bit_offset_of,
|
||||
.param_count = 2,
|
||||
"@bitOffsetOf",
|
||||
.{
|
||||
.tag = .bit_offset_of,
|
||||
.param_count = 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@boolToInt",
|
||||
.{
|
||||
.tag = .bool_to_int,
|
||||
.param_count = 1,
|
||||
"@boolToInt",
|
||||
.{
|
||||
.tag = .bool_to_int,
|
||||
.param_count = 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@bitSizeOf",
|
||||
.{
|
||||
.tag = .bit_size_of,
|
||||
.param_count = 1,
|
||||
"@bitSizeOf",
|
||||
.{
|
||||
.tag = .bit_size_of,
|
||||
.param_count = 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@breakpoint",
|
||||
.{
|
||||
.tag = .breakpoint,
|
||||
.param_count = 0,
|
||||
"@breakpoint",
|
||||
.{
|
||||
.tag = .breakpoint,
|
||||
.param_count = 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@mulAdd",
|
||||
.{
|
||||
.tag = .mul_add,
|
||||
.param_count = 4,
|
||||
"@mulAdd",
|
||||
.{
|
||||
.tag = .mul_add,
|
||||
.param_count = 4,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@byteSwap",
|
||||
.{
|
||||
.tag = .byte_swap,
|
||||
.param_count = 2,
|
||||
"@byteSwap",
|
||||
.{
|
||||
.tag = .byte_swap,
|
||||
.param_count = 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@bitReverse",
|
||||
.{
|
||||
.tag = .bit_reverse,
|
||||
.param_count = 2,
|
||||
"@bitReverse",
|
||||
.{
|
||||
.tag = .bit_reverse,
|
||||
.param_count = 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@byteOffsetOf",
|
||||
.{
|
||||
.tag = .byte_offset_of,
|
||||
.param_count = 2,
|
||||
"@byteOffsetOf",
|
||||
.{
|
||||
.tag = .byte_offset_of,
|
||||
.param_count = 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@call",
|
||||
.{
|
||||
.tag = .call,
|
||||
.needs_mem_loc = true,
|
||||
.param_count = 3,
|
||||
"@call",
|
||||
.{
|
||||
.tag = .call,
|
||||
.needs_mem_loc = true,
|
||||
.param_count = 3,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@cDefine",
|
||||
.{
|
||||
.tag = .c_define,
|
||||
.param_count = 2,
|
||||
"@cDefine",
|
||||
.{
|
||||
.tag = .c_define,
|
||||
.param_count = 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@cImport",
|
||||
.{
|
||||
.tag = .c_import,
|
||||
.param_count = 1,
|
||||
"@cImport",
|
||||
.{
|
||||
.tag = .c_import,
|
||||
.param_count = 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@cInclude",
|
||||
.{
|
||||
.tag = .c_include,
|
||||
.param_count = 1,
|
||||
"@cInclude",
|
||||
.{
|
||||
.tag = .c_include,
|
||||
.param_count = 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@clz",
|
||||
.{
|
||||
.tag = .clz,
|
||||
.param_count = 2,
|
||||
"@clz",
|
||||
.{
|
||||
.tag = .clz,
|
||||
.param_count = 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@cmpxchgStrong",
|
||||
.{
|
||||
.tag = .cmpxchg_strong,
|
||||
.param_count = 6,
|
||||
"@cmpxchgStrong",
|
||||
.{
|
||||
.tag = .cmpxchg_strong,
|
||||
.param_count = 6,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@cmpxchgWeak",
|
||||
.{
|
||||
.tag = .cmpxchg_weak,
|
||||
.param_count = 6,
|
||||
"@cmpxchgWeak",
|
||||
.{
|
||||
.tag = .cmpxchg_weak,
|
||||
.param_count = 6,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@compileError",
|
||||
.{
|
||||
.tag = .compile_error,
|
||||
.param_count = 1,
|
||||
"@compileError",
|
||||
.{
|
||||
.tag = .compile_error,
|
||||
.param_count = 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@compileLog",
|
||||
.{
|
||||
.tag = .compile_log,
|
||||
.param_count = null,
|
||||
"@compileLog",
|
||||
.{
|
||||
.tag = .compile_log,
|
||||
.param_count = null,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@ctz",
|
||||
.{
|
||||
.tag = .ctz,
|
||||
.param_count = 2,
|
||||
"@ctz",
|
||||
.{
|
||||
.tag = .ctz,
|
||||
.param_count = 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@cUndef",
|
||||
.{
|
||||
.tag = .c_undef,
|
||||
.param_count = 1,
|
||||
"@cUndef",
|
||||
.{
|
||||
.tag = .c_undef,
|
||||
.param_count = 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@divExact",
|
||||
.{
|
||||
.tag = .div_exact,
|
||||
.param_count = 2,
|
||||
"@divExact",
|
||||
.{
|
||||
.tag = .div_exact,
|
||||
.param_count = 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@divFloor",
|
||||
.{
|
||||
.tag = .div_floor,
|
||||
.param_count = 2,
|
||||
"@divFloor",
|
||||
.{
|
||||
.tag = .div_floor,
|
||||
.param_count = 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@divTrunc",
|
||||
.{
|
||||
.tag = .div_trunc,
|
||||
.param_count = 2,
|
||||
"@divTrunc",
|
||||
.{
|
||||
.tag = .div_trunc,
|
||||
.param_count = 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@embedFile",
|
||||
.{
|
||||
.tag = .embed_file,
|
||||
.param_count = 1,
|
||||
"@embedFile",
|
||||
.{
|
||||
.tag = .embed_file,
|
||||
.param_count = 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@enumToInt",
|
||||
.{
|
||||
.tag = .enum_to_int,
|
||||
.param_count = 1,
|
||||
"@enumToInt",
|
||||
.{
|
||||
.tag = .enum_to_int,
|
||||
.param_count = 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@errorName",
|
||||
.{
|
||||
.tag = .error_name,
|
||||
.param_count = 1,
|
||||
"@errorName",
|
||||
.{
|
||||
.tag = .error_name,
|
||||
.param_count = 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@errorReturnTrace",
|
||||
.{
|
||||
.tag = .error_return_trace,
|
||||
.param_count = 0,
|
||||
"@errorReturnTrace",
|
||||
.{
|
||||
.tag = .error_return_trace,
|
||||
.param_count = 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@errorToInt",
|
||||
.{
|
||||
.tag = .error_to_int,
|
||||
.param_count = 1,
|
||||
"@errorToInt",
|
||||
.{
|
||||
.tag = .error_to_int,
|
||||
.param_count = 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@errSetCast",
|
||||
.{
|
||||
.tag = .err_set_cast,
|
||||
.param_count = 2,
|
||||
"@errSetCast",
|
||||
.{
|
||||
.tag = .err_set_cast,
|
||||
.param_count = 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@export",
|
||||
.{
|
||||
.tag = .@"export",
|
||||
.param_count = 2,
|
||||
"@export",
|
||||
.{
|
||||
.tag = .@"export",
|
||||
.param_count = 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@fence",
|
||||
.{
|
||||
.tag = .fence,
|
||||
.param_count = 0,
|
||||
"@fence",
|
||||
.{
|
||||
.tag = .fence,
|
||||
.param_count = 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@field",
|
||||
.{
|
||||
.tag = .field,
|
||||
.needs_mem_loc = true,
|
||||
.param_count = 2,
|
||||
.allows_lvalue = true,
|
||||
"@field",
|
||||
.{
|
||||
.tag = .field,
|
||||
.needs_mem_loc = true,
|
||||
.param_count = 2,
|
||||
.allows_lvalue = true,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@fieldParentPtr",
|
||||
.{
|
||||
.tag = .field_parent_ptr,
|
||||
.param_count = 3,
|
||||
"@fieldParentPtr",
|
||||
.{
|
||||
.tag = .field_parent_ptr,
|
||||
.param_count = 3,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@floatCast",
|
||||
.{
|
||||
.tag = .float_cast,
|
||||
.param_count = 1,
|
||||
"@floatCast",
|
||||
.{
|
||||
.tag = .float_cast,
|
||||
.param_count = 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@floatToInt",
|
||||
.{
|
||||
.tag = .float_to_int,
|
||||
.param_count = 1,
|
||||
"@floatToInt",
|
||||
.{
|
||||
.tag = .float_to_int,
|
||||
.param_count = 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@frame",
|
||||
.{
|
||||
.tag = .frame,
|
||||
.param_count = 0,
|
||||
"@frame",
|
||||
.{
|
||||
.tag = .frame,
|
||||
.param_count = 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@Frame",
|
||||
.{
|
||||
.tag = .Frame,
|
||||
.param_count = 1,
|
||||
"@Frame",
|
||||
.{
|
||||
.tag = .Frame,
|
||||
.param_count = 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@frameAddress",
|
||||
.{
|
||||
.tag = .frame_address,
|
||||
.param_count = 0,
|
||||
"@frameAddress",
|
||||
.{
|
||||
.tag = .frame_address,
|
||||
.param_count = 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@frameSize",
|
||||
.{
|
||||
.tag = .frame_size,
|
||||
.param_count = 1,
|
||||
"@frameSize",
|
||||
.{
|
||||
.tag = .frame_size,
|
||||
.param_count = 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@hasDecl",
|
||||
.{
|
||||
.tag = .has_decl,
|
||||
.param_count = 2,
|
||||
"@hasDecl",
|
||||
.{
|
||||
.tag = .has_decl,
|
||||
.param_count = 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@hasField",
|
||||
.{
|
||||
.tag = .has_field,
|
||||
.param_count = 2,
|
||||
"@hasField",
|
||||
.{
|
||||
.tag = .has_field,
|
||||
.param_count = 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@import",
|
||||
.{
|
||||
.tag = .import,
|
||||
.param_count = 1,
|
||||
"@import",
|
||||
.{
|
||||
.tag = .import,
|
||||
.param_count = 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@intCast",
|
||||
.{
|
||||
.tag = .int_cast,
|
||||
.param_count = 1,
|
||||
"@intCast",
|
||||
.{
|
||||
.tag = .int_cast,
|
||||
.param_count = 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@intToEnum",
|
||||
.{
|
||||
.tag = .int_to_enum,
|
||||
.param_count = 1,
|
||||
"@intToEnum",
|
||||
.{
|
||||
.tag = .int_to_enum,
|
||||
.param_count = 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@intToError",
|
||||
.{
|
||||
.tag = .int_to_error,
|
||||
.param_count = 1,
|
||||
"@intToError",
|
||||
.{
|
||||
.tag = .int_to_error,
|
||||
.param_count = 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@intToFloat",
|
||||
.{
|
||||
.tag = .int_to_float,
|
||||
.param_count = 1,
|
||||
"@intToFloat",
|
||||
.{
|
||||
.tag = .int_to_float,
|
||||
.param_count = 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@intToPtr",
|
||||
.{
|
||||
.tag = .int_to_ptr,
|
||||
.param_count = 2,
|
||||
"@intToPtr",
|
||||
.{
|
||||
.tag = .int_to_ptr,
|
||||
.param_count = 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@memcpy",
|
||||
.{
|
||||
.tag = .memcpy,
|
||||
.param_count = 3,
|
||||
"@memcpy",
|
||||
.{
|
||||
.tag = .memcpy,
|
||||
.param_count = 3,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@memset",
|
||||
.{
|
||||
.tag = .memset,
|
||||
.param_count = 3,
|
||||
"@memset",
|
||||
.{
|
||||
.tag = .memset,
|
||||
.param_count = 3,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@wasmMemorySize",
|
||||
.{
|
||||
.tag = .wasm_memory_size,
|
||||
.param_count = 1,
|
||||
"@wasmMemorySize",
|
||||
.{
|
||||
.tag = .wasm_memory_size,
|
||||
.param_count = 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@wasmMemoryGrow",
|
||||
.{
|
||||
.tag = .wasm_memory_grow,
|
||||
.param_count = 2,
|
||||
"@wasmMemoryGrow",
|
||||
.{
|
||||
.tag = .wasm_memory_grow,
|
||||
.param_count = 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@mod",
|
||||
.{
|
||||
.tag = .mod,
|
||||
.param_count = 2,
|
||||
"@mod",
|
||||
.{
|
||||
.tag = .mod,
|
||||
.param_count = 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@mulWithOverflow",
|
||||
.{
|
||||
.tag = .mul_with_overflow,
|
||||
.param_count = 4,
|
||||
"@mulWithOverflow",
|
||||
.{
|
||||
.tag = .mul_with_overflow,
|
||||
.param_count = 4,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@panic",
|
||||
.{
|
||||
.tag = .panic,
|
||||
.param_count = 1,
|
||||
"@panic",
|
||||
.{
|
||||
.tag = .panic,
|
||||
.param_count = 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@popCount",
|
||||
.{
|
||||
.tag = .pop_count,
|
||||
.param_count = 2,
|
||||
"@popCount",
|
||||
.{
|
||||
.tag = .pop_count,
|
||||
.param_count = 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@ptrCast",
|
||||
.{
|
||||
.tag = .ptr_cast,
|
||||
.param_count = 2,
|
||||
"@ptrCast",
|
||||
.{
|
||||
.tag = .ptr_cast,
|
||||
.param_count = 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@ptrToInt",
|
||||
.{
|
||||
.tag = .ptr_to_int,
|
||||
.param_count = 1,
|
||||
"@ptrToInt",
|
||||
.{
|
||||
.tag = .ptr_to_int,
|
||||
.param_count = 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@rem",
|
||||
.{
|
||||
.tag = .rem,
|
||||
.param_count = 2,
|
||||
"@rem",
|
||||
.{
|
||||
.tag = .rem,
|
||||
.param_count = 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@returnAddress",
|
||||
.{
|
||||
.tag = .return_address,
|
||||
.param_count = 0,
|
||||
"@returnAddress",
|
||||
.{
|
||||
.tag = .return_address,
|
||||
.param_count = 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@setAlignStack",
|
||||
.{
|
||||
.tag = .set_align_stack,
|
||||
.param_count = 1,
|
||||
"@setAlignStack",
|
||||
.{
|
||||
.tag = .set_align_stack,
|
||||
.param_count = 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@setCold",
|
||||
.{
|
||||
.tag = .set_cold,
|
||||
.param_count = 1,
|
||||
"@setCold",
|
||||
.{
|
||||
.tag = .set_cold,
|
||||
.param_count = 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@setEvalBranchQuota",
|
||||
.{
|
||||
.tag = .set_eval_branch_quota,
|
||||
.param_count = 1,
|
||||
"@setEvalBranchQuota",
|
||||
.{
|
||||
.tag = .set_eval_branch_quota,
|
||||
.param_count = 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@setFloatMode",
|
||||
.{
|
||||
.tag = .set_float_mode,
|
||||
.param_count = 1,
|
||||
"@setFloatMode",
|
||||
.{
|
||||
.tag = .set_float_mode,
|
||||
.param_count = 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@setRuntimeSafety",
|
||||
.{
|
||||
.tag = .set_runtime_safety,
|
||||
.param_count = 1,
|
||||
"@setRuntimeSafety",
|
||||
.{
|
||||
.tag = .set_runtime_safety,
|
||||
.param_count = 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@shlExact",
|
||||
.{
|
||||
.tag = .shl_exact,
|
||||
.param_count = 2,
|
||||
"@shlExact",
|
||||
.{
|
||||
.tag = .shl_exact,
|
||||
.param_count = 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@shlWithOverflow",
|
||||
.{
|
||||
.tag = .shl_with_overflow,
|
||||
.param_count = 4,
|
||||
"@shlWithOverflow",
|
||||
.{
|
||||
.tag = .shl_with_overflow,
|
||||
.param_count = 4,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@shrExact",
|
||||
.{
|
||||
.tag = .shr_exact,
|
||||
.param_count = 2,
|
||||
"@shrExact",
|
||||
.{
|
||||
.tag = .shr_exact,
|
||||
.param_count = 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@shuffle",
|
||||
.{
|
||||
.tag = .shuffle,
|
||||
.param_count = 4,
|
||||
"@shuffle",
|
||||
.{
|
||||
.tag = .shuffle,
|
||||
.param_count = 4,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@sizeOf",
|
||||
.{
|
||||
.tag = .size_of,
|
||||
.param_count = 1,
|
||||
"@sizeOf",
|
||||
.{
|
||||
.tag = .size_of,
|
||||
.param_count = 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@splat",
|
||||
.{
|
||||
.tag = .splat,
|
||||
.needs_mem_loc = true,
|
||||
.param_count = 2,
|
||||
"@splat",
|
||||
.{
|
||||
.tag = .splat,
|
||||
.needs_mem_loc = true,
|
||||
.param_count = 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@reduce",
|
||||
.{
|
||||
.tag = .reduce,
|
||||
.param_count = 2,
|
||||
"@reduce",
|
||||
.{
|
||||
.tag = .reduce,
|
||||
.param_count = 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@src",
|
||||
.{
|
||||
.tag = .src,
|
||||
.needs_mem_loc = true,
|
||||
.param_count = 0,
|
||||
"@src",
|
||||
.{
|
||||
.tag = .src,
|
||||
.needs_mem_loc = true,
|
||||
.param_count = 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@sqrt",
|
||||
.{
|
||||
.tag = .sqrt,
|
||||
.param_count = 1,
|
||||
"@sqrt",
|
||||
.{
|
||||
.tag = .sqrt,
|
||||
.param_count = 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@sin",
|
||||
.{
|
||||
.tag = .sin,
|
||||
.param_count = 1,
|
||||
"@sin",
|
||||
.{
|
||||
.tag = .sin,
|
||||
.param_count = 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@cos",
|
||||
.{
|
||||
.tag = .cos,
|
||||
.param_count = 1,
|
||||
"@cos",
|
||||
.{
|
||||
.tag = .cos,
|
||||
.param_count = 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@exp",
|
||||
.{
|
||||
.tag = .exp,
|
||||
.param_count = 1,
|
||||
"@exp",
|
||||
.{
|
||||
.tag = .exp,
|
||||
.param_count = 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@exp2",
|
||||
.{
|
||||
.tag = .exp2,
|
||||
.param_count = 1,
|
||||
"@exp2",
|
||||
.{
|
||||
.tag = .exp2,
|
||||
.param_count = 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@log",
|
||||
.{
|
||||
.tag = .log,
|
||||
.param_count = 1,
|
||||
"@log",
|
||||
.{
|
||||
.tag = .log,
|
||||
.param_count = 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@log2",
|
||||
.{
|
||||
.tag = .log2,
|
||||
.param_count = 1,
|
||||
"@log2",
|
||||
.{
|
||||
.tag = .log2,
|
||||
.param_count = 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@log10",
|
||||
.{
|
||||
.tag = .log10,
|
||||
.param_count = 1,
|
||||
"@log10",
|
||||
.{
|
||||
.tag = .log10,
|
||||
.param_count = 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@fabs",
|
||||
.{
|
||||
.tag = .fabs,
|
||||
.param_count = 1,
|
||||
"@fabs",
|
||||
.{
|
||||
.tag = .fabs,
|
||||
.param_count = 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@floor",
|
||||
.{
|
||||
.tag = .floor,
|
||||
.param_count = 1,
|
||||
"@floor",
|
||||
.{
|
||||
.tag = .floor,
|
||||
.param_count = 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@ceil",
|
||||
.{
|
||||
.tag = .ceil,
|
||||
.param_count = 1,
|
||||
"@ceil",
|
||||
.{
|
||||
.tag = .ceil,
|
||||
.param_count = 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@trunc",
|
||||
.{
|
||||
.tag = .trunc,
|
||||
.param_count = 1,
|
||||
"@trunc",
|
||||
.{
|
||||
.tag = .trunc,
|
||||
.param_count = 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@round",
|
||||
.{
|
||||
.tag = .round,
|
||||
.param_count = 1,
|
||||
"@round",
|
||||
.{
|
||||
.tag = .round,
|
||||
.param_count = 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@subWithOverflow",
|
||||
.{
|
||||
.tag = .sub_with_overflow,
|
||||
.param_count = 4,
|
||||
"@subWithOverflow",
|
||||
.{
|
||||
.tag = .sub_with_overflow,
|
||||
.param_count = 4,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@tagName",
|
||||
.{
|
||||
.tag = .tag_name,
|
||||
.param_count = 1,
|
||||
"@tagName",
|
||||
.{
|
||||
.tag = .tag_name,
|
||||
.param_count = 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@This",
|
||||
.{
|
||||
.tag = .This,
|
||||
.param_count = 0,
|
||||
"@This",
|
||||
.{
|
||||
.tag = .This,
|
||||
.param_count = 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@truncate",
|
||||
.{
|
||||
.tag = .truncate,
|
||||
.param_count = 2,
|
||||
"@truncate",
|
||||
.{
|
||||
.tag = .truncate,
|
||||
.param_count = 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@Type",
|
||||
.{
|
||||
.tag = .Type,
|
||||
.param_count = 1,
|
||||
"@Type",
|
||||
.{
|
||||
.tag = .Type,
|
||||
.param_count = 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@typeInfo",
|
||||
.{
|
||||
.tag = .type_info,
|
||||
.param_count = 1,
|
||||
"@typeInfo",
|
||||
.{
|
||||
.tag = .type_info,
|
||||
.param_count = 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@typeName",
|
||||
.{
|
||||
.tag = .type_name,
|
||||
.param_count = 1,
|
||||
"@typeName",
|
||||
.{
|
||||
.tag = .type_name,
|
||||
.param_count = 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@TypeOf",
|
||||
.{
|
||||
.tag = .TypeOf,
|
||||
.param_count = null,
|
||||
"@TypeOf",
|
||||
.{
|
||||
.tag = .TypeOf,
|
||||
.param_count = null,
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
"@unionInit",
|
||||
.{
|
||||
.tag = .union_init,
|
||||
.needs_mem_loc = true,
|
||||
.param_count = 3,
|
||||
"@unionInit",
|
||||
.{
|
||||
.tag = .union_init,
|
||||
.needs_mem_loc = true,
|
||||
.param_count = 3,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
+9
-8
@@ -430,12 +430,12 @@ pub const Scope = struct {
|
||||
/// Asserts the scope is a child of a File and has an AST tree and returns the tree.
|
||||
pub fn tree(self: *Scope) *const ast.Tree {
|
||||
switch (self.tag) {
|
||||
.file => return self.cast(File).?.tree,
|
||||
.block => return self.cast(Block).?.src_decl.container.file_scope.tree,
|
||||
.gen_zir => return self.cast(GenZIR).?.decl.container.file_scope.tree,
|
||||
.local_val => return self.cast(LocalVal).?.gen_zir.decl.container.file_scope.tree,
|
||||
.local_ptr => return self.cast(LocalPtr).?.gen_zir.decl.container.file_scope.tree,
|
||||
.container => return self.cast(Container).?.file_scope.tree,
|
||||
.file => return &self.cast(File).?.tree,
|
||||
.block => return &self.cast(Block).?.src_decl.container.file_scope.tree,
|
||||
.gen_zir => return &self.cast(GenZIR).?.decl.container.file_scope.tree,
|
||||
.local_val => return &self.cast(LocalVal).?.gen_zir.decl.container.file_scope.tree,
|
||||
.local_ptr => return &self.cast(LocalPtr).?.gen_zir.decl.container.file_scope.tree,
|
||||
.container => return &self.cast(Container).?.file_scope.tree,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1612,6 +1612,7 @@ fn astgenAndSemaVarDecl(
|
||||
.decl = decl,
|
||||
.arena = &type_scope_arena.allocator,
|
||||
.parent = &decl.container.base,
|
||||
.force_comptime = true,
|
||||
};
|
||||
defer type_scope.instructions.deinit(mod.gpa);
|
||||
|
||||
@@ -1630,7 +1631,7 @@ fn astgenAndSemaVarDecl(
|
||||
} else {
|
||||
return mod.failTok(
|
||||
&block_scope.base,
|
||||
tree.firstToken(var_decl),
|
||||
var_decl.ast.mut_token,
|
||||
"unable to infer variable type",
|
||||
.{},
|
||||
);
|
||||
@@ -1639,7 +1640,7 @@ fn astgenAndSemaVarDecl(
|
||||
if (is_mutable and !var_info.ty.isValidVarType(is_extern)) {
|
||||
return mod.failTok(
|
||||
&block_scope.base,
|
||||
tree.firstToken(var_decl),
|
||||
var_decl.ast.mut_token,
|
||||
"variable of type '{}' must be const",
|
||||
.{var_info.ty},
|
||||
);
|
||||
|
||||
+473
-226
@@ -59,6 +59,8 @@ pub const ResultLoc = union(enum) {
|
||||
|
||||
pub fn typeExpr(mod: *Module, scope: *Scope, type_node: ast.Node.Index) InnerError!*zir.Inst {
|
||||
const tree = scope.tree();
|
||||
const token_starts = tree.tokens.items(.start);
|
||||
|
||||
const type_src = token_starts[tree.firstToken(type_node)];
|
||||
const type_type = try addZIRInstConst(mod, scope, type_src, .{
|
||||
.ty = Type.initTag(.type),
|
||||
@@ -76,13 +78,17 @@ fn lvalExpr(mod: *Module, scope: *Scope, node: ast.Node.Index) InnerError!*zir.I
|
||||
.root => unreachable,
|
||||
.@"usingnamespace" => unreachable,
|
||||
.test_decl => unreachable,
|
||||
.doc_comment => unreachable,
|
||||
.var_decl => unreachable,
|
||||
.global_var_decl => unreachable,
|
||||
.local_var_decl => unreachable,
|
||||
.simple_var_decl => unreachable,
|
||||
.aligned_var_decl => unreachable,
|
||||
.switch_case => unreachable,
|
||||
.switch_else => unreachable,
|
||||
.switch_case_one => unreachable,
|
||||
.container_field_init => unreachable,
|
||||
.container_field_align => unreachable,
|
||||
.container_field => unreachable,
|
||||
.asm_output => unreachable,
|
||||
.asm_input => unreachable,
|
||||
|
||||
.assign,
|
||||
.assign_bit_and,
|
||||
@@ -122,58 +128,107 @@ fn lvalExpr(mod: *Module, scope: *Scope, node: ast.Node.Index) InnerError!*zir.I
|
||||
.bool_and,
|
||||
.bool_or,
|
||||
.@"asm",
|
||||
.asm_simple,
|
||||
.string_literal,
|
||||
.integer_literal,
|
||||
.call,
|
||||
.@"unreachable",
|
||||
.call_comma,
|
||||
.async_call,
|
||||
.async_call_comma,
|
||||
.call_one,
|
||||
.call_one_comma,
|
||||
.async_call_one,
|
||||
.async_call_one_comma,
|
||||
.unreachable_literal,
|
||||
.@"return",
|
||||
.@"if",
|
||||
.if_simple,
|
||||
.@"while",
|
||||
.while_simple,
|
||||
.while_cont,
|
||||
.bool_not,
|
||||
.address_of,
|
||||
.float_literal,
|
||||
.undefined_literal,
|
||||
.bool_literal,
|
||||
.true_literal,
|
||||
.false_literal,
|
||||
.null_literal,
|
||||
.optional_type,
|
||||
.block,
|
||||
.labeled_block,
|
||||
.block_semicolon,
|
||||
.block_two,
|
||||
.block_two_semicolon,
|
||||
.@"break",
|
||||
.PtrType,
|
||||
.ptr_type_aligned,
|
||||
.ptr_type_sentinel,
|
||||
.ptr_type,
|
||||
.ptr_type_bit_range,
|
||||
.array_type,
|
||||
.array_type_sentinel,
|
||||
.enum_literal,
|
||||
.MultilineStringLiteral,
|
||||
.multiline_string_literal,
|
||||
.char_literal,
|
||||
.@"defer",
|
||||
.@"errdefer",
|
||||
.@"catch",
|
||||
.error_union,
|
||||
.merge_error_sets,
|
||||
.range,
|
||||
.switch_range,
|
||||
.@"await",
|
||||
.bit_not,
|
||||
.negation,
|
||||
.negation_wrap,
|
||||
.@"resume",
|
||||
.@"try",
|
||||
.slice_type,
|
||||
.slice,
|
||||
.ArrayInitializer,
|
||||
.ArrayInitializerDot,
|
||||
.StructInitializer,
|
||||
.StructInitializerDot,
|
||||
.slice_open,
|
||||
.slice_sentinel,
|
||||
.array_init_one,
|
||||
.array_init_one_comma,
|
||||
.array_init_dot_two,
|
||||
.array_init_dot_two_comma,
|
||||
.array_init_dot,
|
||||
.array_init_dot_comma,
|
||||
.array_init,
|
||||
.array_init_comma,
|
||||
.struct_init_one,
|
||||
.struct_init_one_comma,
|
||||
.struct_init_dot_two,
|
||||
.struct_init_dot_two_comma,
|
||||
.struct_init_dot,
|
||||
.struct_init_dot_comma,
|
||||
.struct_init,
|
||||
.struct_init_comma,
|
||||
.@"switch",
|
||||
.switch_comma,
|
||||
.@"for",
|
||||
.for_simple,
|
||||
.@"suspend",
|
||||
.@"continue",
|
||||
.@"anytype",
|
||||
.error_type,
|
||||
.FnProto,
|
||||
.fn_proto_simple,
|
||||
.fn_proto_multi,
|
||||
.fn_proto_one,
|
||||
.fn_proto,
|
||||
.fn_decl,
|
||||
.anyframe_type,
|
||||
.anyframe_literal,
|
||||
.error_set_decl,
|
||||
.ContainerDecl,
|
||||
.container_decl,
|
||||
.container_decl_comma,
|
||||
.container_decl_two,
|
||||
.container_decl_two_comma,
|
||||
.container_decl_arg,
|
||||
.container_decl_arg_comma,
|
||||
.tagged_union,
|
||||
.tagged_union_comma,
|
||||
.tagged_union_two,
|
||||
.tagged_union_two_comma,
|
||||
.tagged_union_enum_tag,
|
||||
.tagged_union_enum_tag_comma,
|
||||
.@"comptime",
|
||||
.@"nosuspend",
|
||||
.error_value,
|
||||
=> return mod.failNode(scope, node, "invalid left-hand side to assignment", .{}),
|
||||
|
||||
.builtin_call,
|
||||
@@ -192,10 +247,10 @@ fn lvalExpr(mod: *Module, scope: *Scope, node: ast.Node.Index) InnerError!*zir.I
|
||||
}
|
||||
},
|
||||
|
||||
// can be assigned to
|
||||
// These can be assigned to.
|
||||
.unwrap_optional,
|
||||
.deref,
|
||||
.period,
|
||||
.field_access,
|
||||
.array_access,
|
||||
.identifier,
|
||||
.grouped_expression,
|
||||
@@ -210,22 +265,33 @@ fn lvalExpr(mod: *Module, scope: *Scope, node: ast.Node.Index) InnerError!*zir.I
|
||||
/// result instruction can be used to inspect whether it is isNoReturn() but that is it,
|
||||
/// it must otherwise not be used.
|
||||
pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) InnerError!*zir.Inst {
|
||||
switch (node.tag) {
|
||||
const tree = scope.tree();
|
||||
const main_tokens = tree.nodes.items(.main_token);
|
||||
const token_tags = tree.tokens.items(.tag);
|
||||
const node_datas = tree.nodes.items(.data);
|
||||
const node_tags = tree.nodes.items(.tag);
|
||||
const token_starts = tree.tokens.items(.start);
|
||||
|
||||
switch (node_tags[node]) {
|
||||
.root => unreachable, // Top-level declaration.
|
||||
.@"usingnamespace" => unreachable, // Top-level declaration.
|
||||
.test_decl => unreachable, // Top-level declaration.
|
||||
.doc_comment => unreachable, // Top-level declaration.
|
||||
.var_decl => unreachable, // Handled in `blockExpr`.
|
||||
.container_field_init => unreachable, // Top-level declaration.
|
||||
.container_field_align => unreachable, // Top-level declaration.
|
||||
.container_field => unreachable, // Top-level declaration.
|
||||
.fn_decl => unreachable, // Top-level declaration.
|
||||
|
||||
.global_var_decl => unreachable, // Handled in `blockExpr`.
|
||||
.local_var_decl => unreachable, // Handled in `blockExpr`.
|
||||
.simple_var_decl => unreachable, // Handled in `blockExpr`.
|
||||
.aligned_var_decl => unreachable, // Handled in `blockExpr`.
|
||||
|
||||
.switch_case => unreachable, // Handled in `switchExpr`.
|
||||
.switch_else => unreachable, // Handled in `switchExpr`.
|
||||
.range => unreachable, // Handled in `switchExpr`.
|
||||
.Else => unreachable, // Handled explicitly the control flow expression functions.
|
||||
.Payload => unreachable, // Handled explicitly.
|
||||
.PointerPayload => unreachable, // Handled explicitly.
|
||||
.PointerIndexPayload => unreachable, // Handled explicitly.
|
||||
.ErrorTag => unreachable, // Handled explicitly.
|
||||
.FieldInitializer => unreachable, // Handled explicitly.
|
||||
.ContainerField => unreachable, // Handled explicitly.
|
||||
.switch_case_one => unreachable, // Handled in `switchExpr`.
|
||||
.switch_range => unreachable, // Handled in `switchExpr`.
|
||||
|
||||
.asm_output => unreachable, // Handled in `asmExpr`.
|
||||
.asm_input => unreachable, // Handled in `asmExpr`.
|
||||
|
||||
.assign => return rvalueVoid(mod, scope, rl, node, try assign(mod, scope, node)),
|
||||
.assign_bit_and => return rvalueVoid(mod, scope, rl, node, try assignOp(mod, scope, node, .bit_and)),
|
||||
@@ -276,30 +342,28 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) In
|
||||
|
||||
.identifier => return identifier(mod, scope, rl, node),
|
||||
|
||||
.asm_simple => return assembly(mod, scope, rl, tree.asmSimple(node)),
|
||||
.@"asm" => return assembly(mod, scope, rl, tree.asmFull(node)),
|
||||
.asm_simple => return asmExpr(mod, scope, rl, tree.asmSimple(node)),
|
||||
.@"asm" => return asmExpr(mod, scope, rl, tree.asmFull(node)),
|
||||
|
||||
.string_literal => return stringLiteral(mod, scope, rl, node),
|
||||
.multiline_string_literal => return multilineStringLiteral(mod, scope, rl, node),
|
||||
|
||||
.integer_literal => return integerLiteral(mod, scope, rl, node),
|
||||
|
||||
.builtin_call => return builtinCall(mod, scope, rl, node),
|
||||
|
||||
.builtin_call_two, .builtin_call_two_comma => {
|
||||
if (datas[node].lhs == 0) {
|
||||
if (node_datas[node].lhs == 0) {
|
||||
const params = [_]ast.Node.Index{};
|
||||
return builtinCall(mod, scope, rl, node, ¶ms);
|
||||
} else if (datas[node].rhs == 0) {
|
||||
const params = [_]ast.Node.Index{datas[node].lhs};
|
||||
} else if (node_datas[node].rhs == 0) {
|
||||
const params = [_]ast.Node.Index{node_datas[node].lhs};
|
||||
return builtinCall(mod, scope, rl, node, ¶ms);
|
||||
} else {
|
||||
const params = [_]ast.Node.Index{ datas[node].lhs, datas[node].rhs };
|
||||
const params = [_]ast.Node.Index{ node_datas[node].lhs, node_datas[node].rhs };
|
||||
return builtinCall(mod, scope, rl, node, ¶ms);
|
||||
}
|
||||
},
|
||||
.builtin_call, .builtin_call_comma => {
|
||||
const params = tree.extra_data[datas[node].lhs..datas[node].rhs];
|
||||
const params = tree.extra_data[node_datas[node].lhs..node_datas[node].rhs];
|
||||
return builtinCall(mod, scope, rl, node, params);
|
||||
},
|
||||
|
||||
@@ -311,20 +375,20 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) In
|
||||
return callExpr(mod, scope, rl, tree.callFull(node));
|
||||
},
|
||||
|
||||
.@"unreachable" => {
|
||||
.unreachable_literal => {
|
||||
const main_token = main_tokens[node];
|
||||
const src = token_starts[main_token];
|
||||
return addZIRNoOp(mod, scope, src, .unreachable_safe);
|
||||
},
|
||||
.@"return" => return ret(mod, scope, node),
|
||||
.period => return field(mod, scope, rl, node),
|
||||
.field_access => return field(mod, scope, rl, node),
|
||||
.float_literal => return floatLiteral(mod, scope, rl, node),
|
||||
|
||||
.if_simple => return ifExpr(mod, scope, rl, tree.ifSimple(node)),
|
||||
.@"if" => return ifExpr(mode, scope, rl, tree.ifFull(node)),
|
||||
.@"if" => return ifExpr(mod, scope, rl, tree.ifFull(node)),
|
||||
|
||||
.while_simple => return whileExpr(mod, scope, rl, tree.whileSimple(node)),
|
||||
.while_cont => return whileExpr(mod, scope, tree.whileCont(node)),
|
||||
.while_cont => return whileExpr(mod, scope, rl, tree.whileCont(node)),
|
||||
.@"while" => return whileExpr(mod, scope, rl, tree.whileFull(node)),
|
||||
|
||||
.for_simple => return forExpr(mod, scope, rl, tree.forSimple(node)),
|
||||
@@ -389,7 +453,7 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) In
|
||||
return rvalue(mod, scope, rl, result);
|
||||
},
|
||||
.unwrap_optional => {
|
||||
const operand = try expr(mod, scope, rl, node.lhs);
|
||||
const operand = try expr(mod, scope, rl, node_datas[node].lhs);
|
||||
const op: zir.Inst.Tag = switch (rl) {
|
||||
.ref => .optional_payload_safe_ptr,
|
||||
else => .optional_payload_safe,
|
||||
@@ -449,7 +513,7 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) In
|
||||
},
|
||||
.@"catch" => {
|
||||
const catch_token = main_tokens[node];
|
||||
const payload_token: ?TokenIndex = if (token_tags[catch_token + 1] == .pipe)
|
||||
const payload_token: ?ast.TokenIndex = if (token_tags[catch_token + 1] == .pipe)
|
||||
catch_token + 2
|
||||
else
|
||||
null;
|
||||
@@ -506,6 +570,34 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) In
|
||||
null,
|
||||
),
|
||||
},
|
||||
|
||||
.ptr_type_aligned => return ptrType(mod, scope, rl, tree.ptrTypeAligned(node)),
|
||||
.ptr_type_sentinel => return ptrType(mod, scope, rl, tree.ptrTypeSentinel(node)),
|
||||
.ptr_type => return ptrType(mod, scope, rl, tree.ptrType(node)),
|
||||
.ptr_type_bit_range => return ptrType(mod, scope, rl, tree.ptrTypeBitRange(node)),
|
||||
|
||||
.container_decl,
|
||||
.container_decl_comma,
|
||||
=> return containerDecl(mod, scope, rl, tree.containerDecl(node)),
|
||||
.container_decl_two, .container_decl_two_comma => {
|
||||
var buffer: [2]ast.Node.Index = undefined;
|
||||
return containerDecl(mod, scope, rl, tree.containerDeclTwo(&buffer, node));
|
||||
},
|
||||
.container_decl_arg,
|
||||
.container_decl_arg_comma,
|
||||
=> return containerDecl(mod, scope, rl, tree.containerDeclArg(node)),
|
||||
|
||||
.tagged_union,
|
||||
.tagged_union_comma,
|
||||
=> return containerDecl(mod, scope, rl, tree.taggedUnion(node)),
|
||||
.tagged_union_two, .tagged_union_two_comma => {
|
||||
var buffer: [2]ast.Node.Index = undefined;
|
||||
return containerDecl(mod, scope, rl, tree.taggedUnionTwo(&buffer, node));
|
||||
},
|
||||
.tagged_union_enum_tag,
|
||||
.tagged_union_enum_tag_comma,
|
||||
=> return containerDecl(mod, scope, rl, tree.taggedUnionEnumTag(node)),
|
||||
|
||||
.@"break" => return breakExpr(mod, scope, rl, node),
|
||||
.@"continue" => return continueExpr(mod, scope, rl, node),
|
||||
.grouped_expression => return expr(mod, scope, rl, node_datas[node].lhs),
|
||||
@@ -518,12 +610,41 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) In
|
||||
.@"switch", .switch_comma => return switchExpr(mod, scope, rl, node),
|
||||
|
||||
.@"defer" => return mod.failNode(scope, node, "TODO implement astgen.expr for .defer", .{}),
|
||||
.@"errdefer" => return mod.failNode(scope, node, "TODO implement astgen.expr for .errdefer", .{}),
|
||||
.@"await" => return mod.failNode(scope, node, "TODO implement astgen.expr for .await", .{}),
|
||||
.@"resume" => return mod.failNode(scope, node, "TODO implement astgen.expr for .resume", .{}),
|
||||
.@"try" => return mod.failNode(scope, node, "TODO implement astgen.expr for .Try", .{}),
|
||||
|
||||
.array_init_one,
|
||||
.array_init_one_comma,
|
||||
.array_init_dot_two,
|
||||
.array_init_dot_two_comma,
|
||||
.array_init_dot,
|
||||
.array_init_dot_comma,
|
||||
.array_init,
|
||||
.array_init_comma,
|
||||
=> return mod.failNode(scope, node, "TODO implement astgen.expr for array literals", .{}),
|
||||
|
||||
.struct_init_one,
|
||||
.struct_init_one_comma,
|
||||
.struct_init_dot_two,
|
||||
.struct_init_dot_two_comma,
|
||||
.struct_init_dot,
|
||||
.struct_init_dot_comma,
|
||||
.struct_init,
|
||||
.struct_init_comma,
|
||||
=> return mod.failNode(scope, node, "TODO implement astgen.expr for struct literals", .{}),
|
||||
|
||||
.@"suspend" => return mod.failNode(scope, node, "TODO implement astgen.expr for .suspend", .{}),
|
||||
.@"anytype" => return mod.failNode(scope, node, "TODO implement astgen.expr for .anytype", .{}),
|
||||
.fn_proto_simple,
|
||||
.fn_proto_multi,
|
||||
.fn_proto_one,
|
||||
.fn_proto,
|
||||
=> return mod.failNode(scope, node, "TODO implement astgen.expr for function prototypes", .{}),
|
||||
|
||||
.@"nosuspend" => return mod.failNode(scope, node, "TODO implement astgen.expr for .nosuspend", .{}),
|
||||
.error_value => return mod.failNode(scope, node, "TODO implement astgen.expr for .error_value", .{}),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -572,6 +693,8 @@ fn breakExpr(
|
||||
const tree = parent_scope.tree();
|
||||
const node_datas = tree.nodes.items(.data);
|
||||
const main_tokens = tree.nodes.items(.main_token);
|
||||
const token_starts = tree.tokens.items(.start);
|
||||
|
||||
const src = token_starts[main_tokens[node]];
|
||||
const break_label = node_datas[node].lhs;
|
||||
const rhs = node_datas[node].rhs;
|
||||
@@ -646,6 +769,8 @@ fn continueExpr(
|
||||
const tree = parent_scope.tree();
|
||||
const node_datas = tree.nodes.items(.data);
|
||||
const main_tokens = tree.nodes.items(.main_token);
|
||||
const token_starts = tree.tokens.items(.start);
|
||||
|
||||
const src = token_starts[main_tokens[node]];
|
||||
const break_label = node_datas[node].lhs;
|
||||
|
||||
@@ -702,7 +827,7 @@ pub fn blockExpr(
|
||||
const main_tokens = tree.nodes.items(.main_token);
|
||||
const token_tags = tree.tokens.items(.tag);
|
||||
|
||||
const lbrace = main_tokens[node];
|
||||
const lbrace = main_tokens[block_node];
|
||||
if (token_tags[lbrace - 1] == .colon) {
|
||||
return labeledBlockExpr(mod, scope, rl, block_node, statements, .block);
|
||||
}
|
||||
@@ -721,8 +846,9 @@ fn checkLabelRedefinition(mod: *Module, parent_scope: *Scope, label: ast.TokenIn
|
||||
if (gen_zir.label) |prev_label| {
|
||||
if (try tokenIdentEql(mod, parent_scope, label, prev_label.token)) {
|
||||
const tree = parent_scope.tree();
|
||||
const node_datas = tree.nodes.items(.data);
|
||||
const main_tokens = tree.nodes.items(.main_token);
|
||||
const token_starts = tree.tokens.items(.start);
|
||||
|
||||
const label_src = token_starts[label];
|
||||
const prev_label_src = token_starts[prev_label.token];
|
||||
|
||||
@@ -770,9 +896,9 @@ fn labeledBlockExpr(
|
||||
assert(zir_tag == .block or zir_tag == .block_comptime);
|
||||
|
||||
const tree = parent_scope.tree();
|
||||
const node_datas = tree.nodes.items(.data);
|
||||
const main_tokens = tree.nodes.items(.main_token);
|
||||
const token_starts = tree.tokens.items(.start);
|
||||
const token_tags = tree.tokens.items(.tag);
|
||||
|
||||
const lbrace = main_tokens[block_node];
|
||||
const label_token = lbrace - 1;
|
||||
@@ -813,10 +939,10 @@ fn labeledBlockExpr(
|
||||
defer block_scope.labeled_breaks.deinit(mod.gpa);
|
||||
defer block_scope.labeled_store_to_block_ptr_list.deinit(mod.gpa);
|
||||
|
||||
try blockExprStmts(mod, &block_scope.base, block_node, block_node.statements());
|
||||
try blockExprStmts(mod, &block_scope.base, block_node, statements);
|
||||
|
||||
if (!block_scope.label.?.used) {
|
||||
return mod.fail(parent_scope, token_starts[block_node.label], "unused block label", .{});
|
||||
return mod.failTok(parent_scope, label_token, "unused block label", .{});
|
||||
}
|
||||
|
||||
try gen_zir.instructions.append(mod.gpa, &block_inst.base);
|
||||
@@ -860,21 +986,23 @@ fn blockExprStmts(
|
||||
statements: []const ast.Node.Index,
|
||||
) !void {
|
||||
const tree = parent_scope.tree();
|
||||
const node_datas = tree.nodes.items(.data);
|
||||
const main_tokens = tree.nodes.items(.main_token);
|
||||
const token_starts = tree.tokens.items(.start);
|
||||
const node_tags = tree.nodes.items(.tag);
|
||||
|
||||
var block_arena = std.heap.ArenaAllocator.init(mod.gpa);
|
||||
defer block_arena.deinit();
|
||||
|
||||
var scope = parent_scope;
|
||||
for (statements) |statement| {
|
||||
const src = token_starts[statement.firstToken()];
|
||||
const src = token_starts[tree.firstToken(statement)];
|
||||
_ = try addZIRNoOp(mod, scope, src, .dbg_stmt);
|
||||
switch (statement.tag) {
|
||||
.var_decl => {
|
||||
const var_decl_node = statement.castTag(.var_decl).?;
|
||||
scope = try varDecl(mod, scope, var_decl_node, &block_arena.allocator);
|
||||
},
|
||||
switch (node_tags[statement]) {
|
||||
.global_var_decl => scope = try varDecl(mod, scope, &block_arena.allocator, tree.globalVarDecl(statement)),
|
||||
.local_var_decl => scope = try varDecl(mod, scope, &block_arena.allocator, tree.localVarDecl(statement)),
|
||||
.simple_var_decl => scope = try varDecl(mod, scope, &block_arena.allocator, tree.simpleVarDecl(statement)),
|
||||
.aligned_var_decl => scope = try varDecl(mod, scope, &block_arena.allocator, tree.alignedVarDecl(statement)),
|
||||
|
||||
.assign => try assign(mod, scope, statement),
|
||||
.assign_bit_and => try assignOp(mod, scope, statement, .bit_and),
|
||||
.assign_bit_or => try assignOp(mod, scope, statement, .bit_or),
|
||||
@@ -903,20 +1031,23 @@ fn blockExprStmts(
|
||||
fn varDecl(
|
||||
mod: *Module,
|
||||
scope: *Scope,
|
||||
node: *ast.Node.var_decl,
|
||||
block_arena: *Allocator,
|
||||
var_decl: ast.full.VarDecl,
|
||||
) InnerError!*Scope {
|
||||
if (node.getComptimeToken()) |comptime_token| {
|
||||
if (var_decl.comptime_token) |comptime_token| {
|
||||
return mod.failTok(scope, comptime_token, "TODO implement comptime locals", .{});
|
||||
}
|
||||
if (node.getAlignNode()) |align_node| {
|
||||
return mod.failNode(scope, align_node, "TODO implement alignment on locals", .{});
|
||||
if (var_decl.ast.align_node != 0) {
|
||||
return mod.failNode(scope, var_decl.ast.align_node, "TODO implement alignment on locals", .{});
|
||||
}
|
||||
const tree = scope.tree();
|
||||
const node_datas = tree.nodes.items(.data);
|
||||
const main_tokens = tree.nodes.items(.main_token);
|
||||
const name_src = token_starts[node.name_token];
|
||||
const ident_name = try mod.identifierTokenString(scope, node.name_token);
|
||||
const token_starts = tree.tokens.items(.start);
|
||||
const token_tags = tree.tokens.items(.tag);
|
||||
|
||||
const name_token = var_decl.ast.mut_token + 1;
|
||||
const name_src = token_starts[name_token];
|
||||
const ident_name = try mod.identifierTokenString(scope, name_token);
|
||||
|
||||
// Local variables shadowing detection, including function parameters.
|
||||
{
|
||||
@@ -962,20 +1093,21 @@ fn varDecl(
|
||||
// TODO add note for other definition
|
||||
return mod.fail(scope, name_src, "redefinition of '{s}'", .{ident_name});
|
||||
}
|
||||
const init_node = node.getInitNode() orelse
|
||||
if (var_decl.ast.init_node == 0) {
|
||||
return mod.fail(scope, name_src, "variables must be initialized", .{});
|
||||
}
|
||||
|
||||
switch (tree.token_ids[node.mut_token]) {
|
||||
switch (token_tags[var_decl.ast.mut_token]) {
|
||||
.keyword_const => {
|
||||
// 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.
|
||||
if (!nodeMayNeedMemoryLocation(init_node, scope)) {
|
||||
const result_loc: ResultLoc = if (node.getTypeNode()) |type_node|
|
||||
.{ .ty = try typeExpr(mod, scope, type_node) }
|
||||
if (!nodeMayNeedMemoryLocation(scope, var_decl.ast.init_node)) {
|
||||
const result_loc: ResultLoc = if (var_decl.ast.type_node != 0)
|
||||
.{ .ty = try typeExpr(mod, scope, var_decl.ast.type_node) }
|
||||
else
|
||||
.none;
|
||||
const init_inst = try expr(mod, scope, result_loc, init_node);
|
||||
const init_inst = try expr(mod, scope, result_loc, var_decl.ast.init_node);
|
||||
const sub_scope = try block_arena.create(Scope.LocalVal);
|
||||
sub_scope.* = .{
|
||||
.parent = scope,
|
||||
@@ -999,8 +1131,8 @@ fn varDecl(
|
||||
|
||||
var resolve_inferred_alloc: ?*zir.Inst = null;
|
||||
var opt_type_inst: ?*zir.Inst = null;
|
||||
if (node.getTypeNode()) |type_node| {
|
||||
const type_inst = try typeExpr(mod, &init_scope.base, type_node);
|
||||
if (var_decl.ast.type_node != 0) {
|
||||
const type_inst = try typeExpr(mod, &init_scope.base, var_decl.ast.type_node);
|
||||
opt_type_inst = type_inst;
|
||||
init_scope.rl_ptr = try addZIRUnOp(mod, &init_scope.base, name_src, .alloc, type_inst);
|
||||
} else {
|
||||
@@ -1009,7 +1141,7 @@ fn varDecl(
|
||||
init_scope.rl_ptr = &alloc.base;
|
||||
}
|
||||
const init_result_loc: ResultLoc = .{ .block_ptr = &init_scope };
|
||||
const init_inst = try expr(mod, &init_scope.base, init_result_loc, init_node);
|
||||
const init_inst = try expr(mod, &init_scope.base, init_result_loc, var_decl.ast.init_node);
|
||||
const parent_zir = &scope.getGenZIR().instructions;
|
||||
if (init_scope.rvalue_rl_count == 1) {
|
||||
// Result location pointer not used. We don't need an alloc for this
|
||||
@@ -1069,8 +1201,11 @@ fn varDecl(
|
||||
},
|
||||
.keyword_var => {
|
||||
var resolve_inferred_alloc: ?*zir.Inst = null;
|
||||
const var_data: struct { result_loc: ResultLoc, alloc: *zir.Inst } = if (node.getTypeNode()) |type_node| a: {
|
||||
const type_inst = try typeExpr(mod, scope, type_node);
|
||||
const var_data: struct {
|
||||
result_loc: ResultLoc,
|
||||
alloc: *zir.Inst,
|
||||
} = if (var_decl.ast.type_node != 0) a: {
|
||||
const type_inst = try typeExpr(mod, scope, var_decl.ast.type_node);
|
||||
const alloc = try addZIRUnOp(mod, scope, name_src, .alloc_mut, type_inst);
|
||||
break :a .{ .alloc = alloc, .result_loc = .{ .ptr = alloc } };
|
||||
} else a: {
|
||||
@@ -1078,7 +1213,7 @@ fn varDecl(
|
||||
resolve_inferred_alloc = &alloc.base;
|
||||
break :a .{ .alloc = &alloc.base, .result_loc = .{ .inferred_ptr = alloc } };
|
||||
};
|
||||
const init_inst = try expr(mod, scope, var_data.result_loc, init_node);
|
||||
const init_inst = try expr(mod, scope, var_data.result_loc, var_decl.ast.init_node);
|
||||
if (resolve_inferred_alloc) |inst| {
|
||||
_ = try addZIRUnOp(mod, scope, name_src, .resolve_inferred_alloc, inst);
|
||||
}
|
||||
@@ -1099,13 +1234,15 @@ fn assign(mod: *Module, scope: *Scope, infix_node: ast.Node.Index) InnerError!vo
|
||||
const tree = scope.tree();
|
||||
const node_datas = tree.nodes.items(.data);
|
||||
const main_tokens = tree.nodes.items(.main_token);
|
||||
const node_tags = tree.nodes.items(.tag);
|
||||
|
||||
const lhs = node_datas[infix_node].lhs;
|
||||
const rhs = node_datas[infix_node].rhs;
|
||||
if (node_tags[lhs] == .identifier) {
|
||||
// This intentionally does not support `@"_"` syntax.
|
||||
const ident_name = tree.tokenSlice(main_tokens[lhs]);
|
||||
if (mem.eql(u8, ident_name, "_")) {
|
||||
_ = try expr(mod, scope, .discard, infix_node.rhs);
|
||||
_ = try expr(mod, scope, .discard, rhs);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1122,6 +1259,7 @@ fn assignOp(
|
||||
const tree = scope.tree();
|
||||
const node_datas = tree.nodes.items(.data);
|
||||
const main_tokens = tree.nodes.items(.main_token);
|
||||
const token_starts = tree.tokens.items(.start);
|
||||
|
||||
const lhs_ptr = try lvalExpr(mod, scope, node_datas[infix_node].lhs);
|
||||
const lhs = try addZIRUnOp(mod, scope, lhs_ptr.src, .deref, lhs_ptr);
|
||||
@@ -1136,6 +1274,7 @@ fn boolNot(mod: *Module, scope: *Scope, node: ast.Node.Index) InnerError!*zir.In
|
||||
const tree = scope.tree();
|
||||
const node_datas = tree.nodes.items(.data);
|
||||
const main_tokens = tree.nodes.items(.main_token);
|
||||
const token_starts = tree.tokens.items(.start);
|
||||
|
||||
const src = token_starts[main_tokens[node]];
|
||||
const bool_type = try addZIRInstConst(mod, scope, src, .{
|
||||
@@ -1150,6 +1289,7 @@ fn bitNot(mod: *Module, scope: *Scope, node: ast.Node.Index) InnerError!*zir.Ins
|
||||
const tree = scope.tree();
|
||||
const node_datas = tree.nodes.items(.data);
|
||||
const main_tokens = tree.nodes.items(.main_token);
|
||||
const token_starts = tree.tokens.items(.start);
|
||||
|
||||
const src = token_starts[main_tokens[node]];
|
||||
const operand = try expr(mod, scope, .none, node_datas[node].lhs);
|
||||
@@ -1165,6 +1305,7 @@ fn negation(
|
||||
const tree = scope.tree();
|
||||
const node_datas = tree.nodes.items(.data);
|
||||
const main_tokens = tree.nodes.items(.main_token);
|
||||
const token_starts = tree.tokens.items(.start);
|
||||
|
||||
const src = token_starts[main_tokens[node]];
|
||||
const lhs = try addZIRInstConst(mod, scope, src, .{
|
||||
@@ -1175,53 +1316,61 @@ fn negation(
|
||||
return addZIRBinOp(mod, scope, src, op_inst_tag, lhs, rhs);
|
||||
}
|
||||
|
||||
fn ptrSliceType(mod: *Module, scope: *Scope, src: usize, ptr_info: *ast.PtrInfo, rhs: *ast.Node, size: std.builtin.TypeInfo.Pointer.Size) InnerError!*zir.Inst {
|
||||
fn ptrType(
|
||||
mod: *Module,
|
||||
scope: *Scope,
|
||||
rl: ResultLoc,
|
||||
ptr_info: ast.full.PtrType,
|
||||
) InnerError!*zir.Inst {
|
||||
const tree = scope.tree();
|
||||
const token_starts = tree.tokens.items(.start);
|
||||
|
||||
const src = token_starts[ptr_info.ast.main_token];
|
||||
|
||||
const simple = ptr_info.allowzero_token == null and
|
||||
ptr_info.align_info == null and
|
||||
ptr_info.ast.align_node == 0 and
|
||||
ptr_info.volatile_token == null and
|
||||
ptr_info.sentinel == null;
|
||||
ptr_info.ast.sentinel == 0;
|
||||
|
||||
if (simple) {
|
||||
const child_type = try typeExpr(mod, scope, rhs);
|
||||
const child_type = try typeExpr(mod, scope, ptr_info.ast.child_type);
|
||||
const mutable = ptr_info.const_token == null;
|
||||
// TODO stage1 type inference bug
|
||||
const T = zir.Inst.Tag;
|
||||
return addZIRUnOp(mod, scope, src, switch (size) {
|
||||
const result = try addZIRUnOp(mod, scope, src, switch (ptr_info.size) {
|
||||
.One => if (mutable) T.single_mut_ptr_type else T.single_const_ptr_type,
|
||||
.Many => if (mutable) T.many_mut_ptr_type else T.many_const_ptr_type,
|
||||
.C => if (mutable) T.c_mut_ptr_type else T.c_const_ptr_type,
|
||||
.Slice => if (mutable) T.mut_slice_type else T.const_slice_type,
|
||||
}, child_type);
|
||||
return rvalue(mod, scope, rl, result);
|
||||
}
|
||||
|
||||
var kw_args: std.meta.fieldInfo(zir.Inst.PtrType, .kw_args).field_type = .{};
|
||||
kw_args.size = size;
|
||||
kw_args.size = ptr_info.size;
|
||||
kw_args.@"allowzero" = ptr_info.allowzero_token != null;
|
||||
if (ptr_info.align_info) |some| {
|
||||
kw_args.@"align" = try expr(mod, scope, .none, some.node);
|
||||
if (some.bit_range) |bit_range| {
|
||||
kw_args.align_bit_start = try expr(mod, scope, .none, bit_range.start);
|
||||
kw_args.align_bit_end = try expr(mod, scope, .none, bit_range.end);
|
||||
if (ptr_info.ast.align_node != 0) {
|
||||
kw_args.@"align" = try expr(mod, scope, .none, ptr_info.ast.align_node);
|
||||
if (ptr_info.ast.bit_range_start != 0) {
|
||||
kw_args.align_bit_start = try expr(mod, scope, .none, ptr_info.ast.bit_range_start);
|
||||
kw_args.align_bit_end = try expr(mod, scope, .none, ptr_info.ast.bit_range_end);
|
||||
}
|
||||
}
|
||||
kw_args.mutable = ptr_info.const_token == null;
|
||||
kw_args.@"volatile" = ptr_info.volatile_token != null;
|
||||
if (ptr_info.sentinel) |some| {
|
||||
kw_args.sentinel = try expr(mod, scope, .none, some);
|
||||
const child_type = try typeExpr(mod, scope, ptr_info.ast.child_type);
|
||||
if (ptr_info.ast.sentinel != 0) {
|
||||
kw_args.sentinel = try expr(mod, scope, .{ .ty = child_type }, ptr_info.ast.sentinel);
|
||||
}
|
||||
|
||||
const child_type = try typeExpr(mod, scope, rhs);
|
||||
if (kw_args.sentinel) |some| {
|
||||
kw_args.sentinel = try addZIRBinOp(mod, scope, some.src, .as, child_type, some);
|
||||
}
|
||||
|
||||
return addZIRInst(mod, scope, src, zir.Inst.PtrType, .{ .child_type = child_type }, kw_args);
|
||||
const result = try addZIRInst(mod, scope, src, zir.Inst.PtrType, .{ .child_type = child_type }, kw_args);
|
||||
return rvalue(mod, scope, rl, result);
|
||||
}
|
||||
|
||||
fn arrayType(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) !*zir.Inst {
|
||||
const tree = scope.tree();
|
||||
const main_tokens = tree.nodes.items(.main_token);
|
||||
const node_datas = tree.nodes.items(.data);
|
||||
const token_starts = tree.tokens.items(.start);
|
||||
|
||||
const src = token_starts[main_tokens[node]];
|
||||
const usize_type = try addZIRInstConst(mod, scope, src, .{
|
||||
.ty = Type.initTag(.type),
|
||||
@@ -1246,6 +1395,9 @@ fn arrayType(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) !
|
||||
fn arrayTypeSentinel(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) !*zir.Inst {
|
||||
const tree = scope.tree();
|
||||
const main_tokens = tree.nodes.items(.main_token);
|
||||
const token_starts = tree.tokens.items(.start);
|
||||
const node_datas = tree.nodes.items(.data);
|
||||
|
||||
const len_node = node_datas[node].lhs;
|
||||
const extra = tree.extraData(node_datas[node].rhs, ast.Node.ArrayTypeSentinel);
|
||||
const src = token_starts[main_tokens[node]];
|
||||
@@ -1274,6 +1426,8 @@ fn containerField(
|
||||
node: *ast.Node.ContainerField,
|
||||
) InnerError!*zir.Inst {
|
||||
const tree = scope.tree();
|
||||
const token_starts = tree.tokens.items(.start);
|
||||
|
||||
const src = token_starts[tree.firstToken(node)];
|
||||
const name = try mod.identifierTokenString(scope, node.name_token);
|
||||
|
||||
@@ -1305,9 +1459,18 @@ fn containerField(
|
||||
});
|
||||
}
|
||||
|
||||
fn containerDecl(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.ContainerDecl) InnerError!*zir.Inst {
|
||||
fn containerDecl(
|
||||
mod: *Module,
|
||||
scope: *Scope,
|
||||
rl: ResultLoc,
|
||||
container_decl: ast.full.ContainerDecl,
|
||||
) InnerError!*zir.Inst {
|
||||
const tree = scope.tree();
|
||||
const src = token_starts[node.kind_token];
|
||||
const token_starts = tree.tokens.items(.start);
|
||||
const node_tags = tree.nodes.items(.tag);
|
||||
const token_tags = tree.tokens.items(.tag);
|
||||
|
||||
const src = token_starts[container_decl.ast.main_token];
|
||||
|
||||
var gen_scope: Scope.GenZIR = .{
|
||||
.parent = scope,
|
||||
@@ -1321,9 +1484,12 @@ fn containerDecl(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Con
|
||||
var fields = std.ArrayList(*zir.Inst).init(mod.gpa);
|
||||
defer fields.deinit();
|
||||
|
||||
for (node.fieldsAndDecls()) |fd| {
|
||||
if (fd.castTag(.ContainerField)) |f| {
|
||||
try fields.append(try containerField(mod, &gen_scope.base, f));
|
||||
for (container_decl.ast.members) |member| {
|
||||
switch (node_tags[member]) {
|
||||
.container_field_init, .container_field_align, .container_field => {
|
||||
try fields.append(try containerField(mod, &gen_scope.base, member));
|
||||
},
|
||||
else => continue,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1332,19 +1498,22 @@ fn containerDecl(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Con
|
||||
const arena = &decl_arena.allocator;
|
||||
|
||||
var layout: std.builtin.TypeInfo.ContainerLayout = .Auto;
|
||||
if (node.layout_token) |some| switch (tree.token_ids[some]) {
|
||||
if (container_decl.layout_token) |some| switch (token_tags[some]) {
|
||||
.keyword_extern => layout = .Extern,
|
||||
.keyword_packed => layout = .Packed,
|
||||
else => unreachable,
|
||||
};
|
||||
|
||||
const container_type = switch (tree.token_ids[node.kind_token]) {
|
||||
// TODO this implementation is incorrect. The types must be created in semantic
|
||||
// analysis, not astgen, because the same ZIR is re-used for multiple inline function calls,
|
||||
// comptime function calls, and generic function instantiations, and these
|
||||
// must result in different instances of container types.
|
||||
const container_type = switch (token_tags[container_decl.ast.main_token]) {
|
||||
.keyword_enum => blk: {
|
||||
const tag_type: ?*zir.Inst = switch (node.init_arg_expr) {
|
||||
.Type => |t| try typeExpr(mod, &gen_scope.base, t),
|
||||
.None => null,
|
||||
.Enum => unreachable,
|
||||
};
|
||||
const tag_type: ?*zir.Inst = if (container_decl.ast.arg != 0)
|
||||
try typeExpr(mod, &gen_scope.base, container_decl.ast.arg)
|
||||
else
|
||||
null;
|
||||
const inst = try addZIRInst(mod, &gen_scope.base, src, zir.Inst.EnumType, .{
|
||||
.fields = try arena.dupe(*zir.Inst, fields.items),
|
||||
}, .{
|
||||
@@ -1367,7 +1536,7 @@ fn containerDecl(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Con
|
||||
break :blk Type.initPayload(&enum_type.base);
|
||||
},
|
||||
.keyword_struct => blk: {
|
||||
assert(node.init_arg_expr == .None);
|
||||
assert(container_decl.ast.arg == 0);
|
||||
const inst = try addZIRInst(mod, &gen_scope.base, src, zir.Inst.StructType, .{
|
||||
.fields = try arena.dupe(*zir.Inst, fields.items),
|
||||
}, .{
|
||||
@@ -1389,21 +1558,16 @@ fn containerDecl(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Con
|
||||
break :blk Type.initPayload(&struct_type.base);
|
||||
},
|
||||
.keyword_union => blk: {
|
||||
const init_inst = switch (node.init_arg_expr) {
|
||||
.Enum => |e| if (e) |t| try typeExpr(mod, &gen_scope.base, t) else null,
|
||||
.None => null,
|
||||
.Type => |t| try typeExpr(mod, &gen_scope.base, t),
|
||||
};
|
||||
const init_kind: zir.Inst.UnionType.InitKind = switch (node.init_arg_expr) {
|
||||
.Enum => .enum_type,
|
||||
.None => .none,
|
||||
.Type => .tag_type,
|
||||
};
|
||||
const init_inst: ?*zir.Inst = if (container_decl.ast.arg != 0)
|
||||
try typeExpr(mod, &gen_scope.base, container_decl.ast.arg)
|
||||
else
|
||||
null;
|
||||
const has_enum_token = container_decl.ast.enum_token != null;
|
||||
const inst = try addZIRInst(mod, &gen_scope.base, src, zir.Inst.UnionType, .{
|
||||
.fields = try arena.dupe(*zir.Inst, fields.items),
|
||||
}, .{
|
||||
.layout = layout,
|
||||
.init_kind = init_kind,
|
||||
.has_enum_token = has_enum_token,
|
||||
.init_inst = init_inst,
|
||||
});
|
||||
const union_type = try arena.create(Type.Payload.Union);
|
||||
@@ -1437,7 +1601,7 @@ fn containerDecl(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Con
|
||||
else => unreachable,
|
||||
};
|
||||
const val = try Value.Tag.ty.create(arena, container_type);
|
||||
const decl = try mod.createContainerDecl(scope, node.kind_token, &decl_arena, .{
|
||||
const decl = try mod.createContainerDecl(scope, container_decl.ast.main_token, &decl_arena, .{
|
||||
.ty = Type.initTag(.type),
|
||||
.val = val,
|
||||
});
|
||||
@@ -1459,6 +1623,7 @@ fn errorSetDecl(
|
||||
const tree = scope.tree();
|
||||
const main_tokens = tree.nodes.items(.main_token);
|
||||
const token_tags = tree.tokens.items(.tag);
|
||||
const token_starts = tree.tokens.items(.start);
|
||||
|
||||
// Count how many fields there are.
|
||||
const error_token = main_tokens[node];
|
||||
@@ -1500,15 +1665,17 @@ fn orelseCatchExpr(
|
||||
mod: *Module,
|
||||
scope: *Scope,
|
||||
rl: ResultLoc,
|
||||
lhs: *ast.Node,
|
||||
lhs: ast.Node.Index,
|
||||
op_token: ast.TokenIndex,
|
||||
cond_op: zir.Inst.Tag,
|
||||
unwrap_op: zir.Inst.Tag,
|
||||
unwrap_code_op: zir.Inst.Tag,
|
||||
rhs: *ast.Node,
|
||||
payload_node: ?*ast.Node,
|
||||
rhs: ast.Node.Index,
|
||||
payload_token: ?ast.TokenIndex,
|
||||
) InnerError!*zir.Inst {
|
||||
const tree = scope.tree();
|
||||
const token_starts = tree.tokens.items(.start);
|
||||
|
||||
const src = token_starts[op_token];
|
||||
|
||||
var block_scope: Scope.GenZIR = .{
|
||||
@@ -1547,12 +1714,11 @@ fn orelseCatchExpr(
|
||||
|
||||
var err_val_scope: Scope.LocalVal = undefined;
|
||||
const then_sub_scope = blk: {
|
||||
const payload = payload_node orelse break :blk &then_scope.base;
|
||||
|
||||
const err_name = tree.tokenSlice(payload.castTag(.Payload).?.error_symbol.firstToken());
|
||||
if (mem.eql(u8, err_name, "_"))
|
||||
break :blk &then_scope.base;
|
||||
|
||||
const payload = payload_token orelse break :blk &then_scope.base;
|
||||
if (mem.eql(u8, tree.tokenSlice(payload), "_")) {
|
||||
return mod.failTok(&then_scope.base, payload, "discard of error capture; omit it instead", .{});
|
||||
}
|
||||
const err_name = try mod.identifierTokenString(scope, payload);
|
||||
err_val_scope = .{
|
||||
.parent = &then_scope.base,
|
||||
.gen_zir = &then_scope,
|
||||
@@ -1685,18 +1851,20 @@ pub fn field(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) I
|
||||
const tree = scope.tree();
|
||||
const token_starts = tree.tokens.items(.start);
|
||||
const main_tokens = tree.nodes.items(.main_token);
|
||||
const node_datas = tree.nodes.items(.data);
|
||||
|
||||
const dot_token = main_tokens[node];
|
||||
const src = token_starts[dot_token];
|
||||
const field_ident = dot_token + 1;
|
||||
const field_name = try mod.identifierTokenString(scope, field_ident);
|
||||
if (rl == .ref) {
|
||||
return addZirInstTag(mod, scope, src, .field_ptr, .{
|
||||
.object = try expr(mod, scope, .ref, node.lhs),
|
||||
.object = try expr(mod, scope, .ref, node_datas[node].lhs),
|
||||
.field_name = field_name,
|
||||
});
|
||||
} else {
|
||||
return rvalue(mod, scope, rl, try addZirInstTag(mod, scope, src, .field_val, .{
|
||||
.object = try expr(mod, scope, .none, node.lhs),
|
||||
.object = try expr(mod, scope, .none, node_datas[node].lhs),
|
||||
.field_name = field_name,
|
||||
}));
|
||||
}
|
||||
@@ -1711,6 +1879,8 @@ fn arrayAccess(
|
||||
const tree = scope.tree();
|
||||
const main_tokens = tree.nodes.items(.main_token);
|
||||
const token_starts = tree.tokens.items(.start);
|
||||
const node_datas = tree.nodes.items(.data);
|
||||
|
||||
const src = token_starts[main_tokens[node]];
|
||||
const usize_type = try addZIRInstConst(mod, scope, src, .{
|
||||
.ty = Type.initTag(.type),
|
||||
@@ -1737,6 +1907,7 @@ fn sliceExpr(
|
||||
) InnerError!*zir.Inst {
|
||||
const tree = scope.tree();
|
||||
const token_starts = tree.tokens.items(.start);
|
||||
|
||||
const src = token_starts[slice.ast.lbracket];
|
||||
|
||||
const usize_type = try addZIRInstConst(mod, scope, src, .{
|
||||
@@ -1786,6 +1957,7 @@ fn simpleBinOp(
|
||||
const tree = scope.tree();
|
||||
const node_datas = tree.nodes.items(.data);
|
||||
const main_tokens = tree.nodes.items(.main_token);
|
||||
const token_starts = tree.tokens.items(.start);
|
||||
|
||||
const lhs = try expr(mod, scope, .none, node_datas[infix_node].lhs);
|
||||
const rhs = try expr(mod, scope, .none, node_datas[infix_node].rhs);
|
||||
@@ -1804,6 +1976,7 @@ fn boolBinOp(
|
||||
const tree = scope.tree();
|
||||
const node_datas = tree.nodes.items(.data);
|
||||
const main_tokens = tree.nodes.items(.main_token);
|
||||
const token_starts = tree.tokens.items(.start);
|
||||
|
||||
const src = token_starts[main_tokens[infix_node]];
|
||||
const bool_type = try addZIRInstConst(mod, scope, src, .{
|
||||
@@ -1899,13 +2072,14 @@ fn ifExpr(
|
||||
defer block_scope.instructions.deinit(mod.gpa);
|
||||
|
||||
const tree = scope.tree();
|
||||
const node_datas = tree.nodes.items(.data);
|
||||
const main_tokens = tree.nodes.items(.main_token);
|
||||
const token_starts = tree.tokens.items(.start);
|
||||
|
||||
const if_src = token_starts[if_full.ast.if_token];
|
||||
|
||||
const cond = c: {
|
||||
// TODO https://github.com/ziglang/zig/issues/7929
|
||||
if (if_full.ast.error_token) |error_token| {
|
||||
if (if_full.error_token) |error_token| {
|
||||
return mod.failTok(scope, error_token, "TODO implement if error union", .{});
|
||||
} else if (if_full.payload_token) |payload_token| {
|
||||
return mod.failTok(scope, payload_token, "TODO implement if optional", .{});
|
||||
@@ -1966,7 +2140,7 @@ fn ifExpr(
|
||||
};
|
||||
} else
|
||||
.{
|
||||
.src = token_starts[tree.lastToken(if_full.then_expr)],
|
||||
.src = token_starts[tree.lastToken(if_full.ast.then_expr)],
|
||||
.result = null,
|
||||
};
|
||||
|
||||
@@ -2042,8 +2216,9 @@ fn whileExpr(
|
||||
defer continue_scope.instructions.deinit(mod.gpa);
|
||||
|
||||
const tree = scope.tree();
|
||||
const node_datas = tree.nodes.items(.data);
|
||||
const main_tokens = tree.nodes.items(.main_token);
|
||||
const token_starts = tree.tokens.items(.start);
|
||||
|
||||
const while_src = token_starts[while_full.ast.while_token];
|
||||
const void_type = try addZIRInstConst(mod, scope, while_src, .{
|
||||
.ty = Type.initTag(.type),
|
||||
@@ -2051,16 +2226,16 @@ fn whileExpr(
|
||||
});
|
||||
const cond = c: {
|
||||
// TODO https://github.com/ziglang/zig/issues/7929
|
||||
if (while_full.ast.error_token) |error_token| {
|
||||
if (while_full.error_token) |error_token| {
|
||||
return mod.failTok(scope, error_token, "TODO implement while error union", .{});
|
||||
} else if (while_full.payload_token) |payload_token| {
|
||||
return mod.failTok(scope, payload_token, "TODO implement while optional", .{});
|
||||
} else {
|
||||
const bool_type = try addZIRInstConst(mod, &block_scope.base, while_src, .{
|
||||
const bool_type = try addZIRInstConst(mod, &continue_scope.base, while_src, .{
|
||||
.ty = Type.initTag(.type),
|
||||
.val = Value.initTag(.bool_type),
|
||||
});
|
||||
break :c try expr(mod, &block_scope.base, .{ .ty = bool_type }, while_full.ast.cond_expr);
|
||||
break :c try expr(mod, &continue_scope.base, .{ .ty = bool_type }, while_full.ast.cond_expr);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2128,7 +2303,7 @@ fn whileExpr(
|
||||
};
|
||||
defer else_scope.instructions.deinit(mod.gpa);
|
||||
|
||||
const else_node = if_full.ast.else_expr;
|
||||
const else_node = while_full.ast.else_expr;
|
||||
const else_info: struct { src: usize, result: ?*zir.Inst } = if (else_node != 0) blk: {
|
||||
loop_scope.break_count += 1;
|
||||
const sub_scope = &else_scope.base;
|
||||
@@ -2138,7 +2313,7 @@ fn whileExpr(
|
||||
};
|
||||
} else
|
||||
.{
|
||||
.src = token_starts[tree.lastToken(then_node)],
|
||||
.src = token_starts[tree.lastToken(while_full.ast.then_expr)],
|
||||
.result = null,
|
||||
};
|
||||
|
||||
@@ -2181,8 +2356,10 @@ fn forExpr(
|
||||
|
||||
// Set up variables and constants.
|
||||
const tree = scope.tree();
|
||||
const node_datas = tree.nodes.items(.data);
|
||||
const main_tokens = tree.nodes.items(.main_token);
|
||||
const token_starts = tree.tokens.items(.start);
|
||||
const token_tags = tree.tokens.items(.tag);
|
||||
|
||||
const for_src = token_starts[for_full.ast.while_token];
|
||||
const index_ptr = blk: {
|
||||
const usize_type = try addZIRInstConst(mod, scope, for_src, .{
|
||||
@@ -2299,7 +2476,7 @@ fn forExpr(
|
||||
else
|
||||
break :blk &then_scope.base;
|
||||
if (mem.eql(u8, tree.tokenSlice(index_token), "_")) {
|
||||
return mod.failTok(&then_scope.base, index_token, "discard of index capture not allowed; omit it instead", .{});
|
||||
return mod.failTok(&then_scope.base, index_token, "discard of index capture; omit it instead", .{});
|
||||
}
|
||||
const index_name = try mod.identifierTokenString(&then_scope.base, index_token);
|
||||
index_scope = .{
|
||||
@@ -2334,7 +2511,7 @@ fn forExpr(
|
||||
};
|
||||
} else
|
||||
.{
|
||||
.src = token_starts[tree.lastToken(then_node)],
|
||||
.src = token_starts[tree.lastToken(for_full.ast.then_expr)],
|
||||
.result = null,
|
||||
};
|
||||
|
||||
@@ -2386,10 +2563,12 @@ fn switchExpr(
|
||||
const node_datas = tree.nodes.items(.data);
|
||||
const main_tokens = tree.nodes.items(.main_token);
|
||||
const token_tags = tree.tokens.items(.tag);
|
||||
const token_starts = tree.tokens.items(.start);
|
||||
const node_tags = tree.nodes.items(.tag);
|
||||
|
||||
const switch_token = main_tokens[switch_node];
|
||||
const target_node = datas[switch_node].lhs;
|
||||
const extra = tree.extraData(datas[switch_node].rhs, ast.switch_node.SubRange);
|
||||
const target_node = node_datas[switch_node].lhs;
|
||||
const extra = tree.extraData(node_datas[switch_node].rhs, ast.Node.SubRange);
|
||||
const case_nodes = tree.extra_data[extra.start..extra.end];
|
||||
|
||||
const switch_src = token_starts[switch_token];
|
||||
@@ -2552,7 +2731,7 @@ fn switchExpr(
|
||||
defer else_scope.instructions.deinit(mod.gpa);
|
||||
|
||||
// Now generate all but the special cases.
|
||||
var special_case: ?ast.Node.Index = null;
|
||||
var special_case: ?ast.full.SwitchCase = null;
|
||||
var items_index: usize = 0;
|
||||
var case_index: usize = 0;
|
||||
for (case_nodes) |case_node| {
|
||||
@@ -2582,7 +2761,7 @@ fn switchExpr(
|
||||
{
|
||||
const item = items.items[items_index];
|
||||
items_index += 1;
|
||||
try switchCaseExpr(mod, &case_scope.base, block_scope.break_result_loc, block, case, target, target_ptr);
|
||||
try switchCaseExpr(mod, &case_scope.base, block_scope.break_result_loc, block, case, target);
|
||||
|
||||
cases[case_index] = .{
|
||||
.item = item,
|
||||
@@ -2638,7 +2817,7 @@ fn switchExpr(
|
||||
|
||||
// reset cond_scope for then_body
|
||||
case_scope.instructions.items.len = 0;
|
||||
try switchCaseExpr(mod, &case_scope.base, block_scope.break_result_loc, block, case, target, target_ptr);
|
||||
try switchCaseExpr(mod, &case_scope.base, block_scope.break_result_loc, block, case, target);
|
||||
condbr.positionals.then_body = .{
|
||||
.instructions = try scope.arena().dupe(*zir.Inst, case_scope.instructions.items),
|
||||
};
|
||||
@@ -2655,7 +2834,7 @@ fn switchExpr(
|
||||
|
||||
// Finally generate else block or a break.
|
||||
if (special_case) |case| {
|
||||
try switchCaseExpr(mod, &else_scope.base, block_scope.break_result_loc, block, case, target, target_ptr);
|
||||
try switchCaseExpr(mod, &else_scope.base, block_scope.break_result_loc, block, case, target);
|
||||
} else {
|
||||
// Not handling all possible cases is a compile error.
|
||||
_ = try addZIRNoOp(mod, &else_scope.base, switch_src, .unreachable_unsafe);
|
||||
@@ -2674,11 +2853,13 @@ fn switchCaseExpr(
|
||||
block: *zir.Inst.Block,
|
||||
case: ast.full.SwitchCase,
|
||||
target: *zir.Inst,
|
||||
target_ptr: ?*zir.Inst,
|
||||
) !void {
|
||||
const tree = scope.tree();
|
||||
const node_datas = tree.nodes.items(.data);
|
||||
const main_tokens = tree.nodes.items(.main_token);
|
||||
const token_starts = tree.tokens.items(.start);
|
||||
const token_tags = tree.tokens.items(.tag);
|
||||
|
||||
const case_src = token_starts[case.ast.arrow_token];
|
||||
const sub_scope = blk: {
|
||||
const payload_token = case.payload_token orelse break :blk scope;
|
||||
@@ -2690,11 +2871,11 @@ fn switchCaseExpr(
|
||||
const value_name = tree.tokenSlice(ident);
|
||||
if (mem.eql(u8, value_name, "_")) {
|
||||
if (is_ptr) {
|
||||
return mod.failTok(scope, payload.ptr_token.?, "pointer modifier invalid on discard", .{});
|
||||
return mod.failTok(scope, payload_token, "pointer modifier invalid on discard", .{});
|
||||
}
|
||||
break :blk scope;
|
||||
}
|
||||
return mod.failNode(scope, payload.value_symbol, "TODO implement switch value payload", .{});
|
||||
return mod.failTok(scope, ident, "TODO implement switch value payload", .{});
|
||||
};
|
||||
|
||||
const case_body = try expr(mod, sub_scope, rl, case.ast.target_expr);
|
||||
@@ -2710,10 +2891,12 @@ fn ret(mod: *Module, scope: *Scope, node: ast.Node.Index) InnerError!*zir.Inst {
|
||||
const tree = scope.tree();
|
||||
const node_datas = tree.nodes.items(.data);
|
||||
const main_tokens = tree.nodes.items(.main_token);
|
||||
const token_starts = tree.tokens.items(.start);
|
||||
|
||||
const src = token_starts[main_tokens[node]];
|
||||
const rhs_node = node_datas[node].lhs;
|
||||
if (rhs_node != 0) {
|
||||
if (nodeMayNeedMemoryLocation(rhs_node, scope)) {
|
||||
if (nodeMayNeedMemoryLocation(scope, rhs_node)) {
|
||||
const ret_ptr = try addZIRNoOp(mod, scope, src, .ret_ptr);
|
||||
const operand = try expr(mod, scope, .{ .ptr = ret_ptr }, rhs_node);
|
||||
return addZIRUnOp(mod, scope, src, .@"return", operand);
|
||||
@@ -2737,8 +2920,8 @@ fn identifier(
|
||||
defer tracy.end();
|
||||
|
||||
const tree = scope.tree();
|
||||
const node_datas = tree.nodes.items(.data);
|
||||
const main_tokens = tree.nodes.items(.main_token);
|
||||
const token_starts = tree.tokens.items(.start);
|
||||
|
||||
const ident_token = main_tokens[ident];
|
||||
const ident_name = try mod.identifierTokenString(scope, ident_token);
|
||||
@@ -2826,6 +3009,27 @@ fn identifier(
|
||||
return mod.failNode(scope, ident, "use of undeclared identifier '{s}'", .{ident_name});
|
||||
}
|
||||
|
||||
fn parseStringLiteral(mod: *Module, scope: *Scope, token: ast.TokenIndex) ![]u8 {
|
||||
const tree = scope.tree();
|
||||
const token_tags = tree.tokens.items(.tag);
|
||||
const token_starts = tree.tokens.items(.start);
|
||||
assert(token_tags[token] == .string_literal);
|
||||
const unparsed = tree.tokenSlice(token);
|
||||
const arena = scope.arena();
|
||||
var bad_index: usize = undefined;
|
||||
const bytes = std.zig.parseStringLiteral(arena, unparsed, &bad_index) catch |err| switch (err) {
|
||||
error.InvalidCharacter => {
|
||||
const bad_byte = unparsed[bad_index];
|
||||
const src = token_starts[token];
|
||||
return mod.fail(scope, src + bad_index, "invalid string literal character: '{c}'", .{
|
||||
bad_byte,
|
||||
});
|
||||
},
|
||||
else => |e| return e,
|
||||
};
|
||||
return bytes;
|
||||
}
|
||||
|
||||
fn stringLiteral(
|
||||
mod: *Module,
|
||||
scope: *Scope,
|
||||
@@ -2833,23 +3037,11 @@ fn stringLiteral(
|
||||
str_lit: ast.Node.Index,
|
||||
) InnerError!*zir.Inst {
|
||||
const tree = scope.tree();
|
||||
const node_datas = tree.nodes.items(.data);
|
||||
const main_tokens = tree.nodes.items(.main_token);
|
||||
const token_starts = tree.tokens.items(.start);
|
||||
|
||||
const str_lit_token = main_tokens[str_lit];
|
||||
const unparsed_bytes = tree.tokenSlice(str_lit_token);
|
||||
const arena = scope.arena();
|
||||
|
||||
var bad_index: usize = undefined;
|
||||
const bytes = std.zig.parseStringLiteral(arena, unparsed_bytes, &bad_index) catch |err| switch (err) {
|
||||
error.InvalidCharacter => {
|
||||
const bad_byte = unparsed_bytes[bad_index];
|
||||
const src = token_starts[str_lit_token];
|
||||
return mod.fail(scope, src + bad_index, "invalid string literal character: '{c}'\n", .{bad_byte});
|
||||
},
|
||||
else => |e| return e,
|
||||
};
|
||||
|
||||
const bytes = try parseStringLiteral(mod, scope, str_lit_token);
|
||||
const src = token_starts[str_lit_token];
|
||||
const str_inst = try addZIRInst(mod, scope, src, zir.Inst.Str, .{ .bytes = bytes }, .{});
|
||||
return rvalue(mod, scope, rl, str_inst);
|
||||
@@ -2864,9 +3056,10 @@ fn multilineStringLiteral(
|
||||
const tree = scope.tree();
|
||||
const node_datas = tree.nodes.items(.data);
|
||||
const main_tokens = tree.nodes.items(.main_token);
|
||||
const token_starts = tree.tokens.items(.start);
|
||||
|
||||
const start = node_datas[node].lhs;
|
||||
const end = node_datas[node].rhs;
|
||||
const start = node_datas[str_lit].lhs;
|
||||
const end = node_datas[str_lit].rhs;
|
||||
|
||||
// Count the number of bytes to allocate.
|
||||
const len: usize = len: {
|
||||
@@ -2905,9 +3098,10 @@ fn multilineStringLiteral(
|
||||
|
||||
fn charLiteral(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) !*zir.Inst {
|
||||
const tree = scope.tree();
|
||||
const node_datas = tree.nodes.items(.data);
|
||||
const main_tokens = tree.nodes.items(.main_token);
|
||||
const main_token = main_tokens[node];
|
||||
const token_starts = tree.tokens.items(.start);
|
||||
|
||||
const src = token_starts[main_token];
|
||||
const slice = tree.tokenSlice(main_token);
|
||||
|
||||
@@ -2934,6 +3128,7 @@ fn integerLiteral(
|
||||
const arena = scope.arena();
|
||||
const tree = scope.tree();
|
||||
const main_tokens = tree.nodes.items(.main_token);
|
||||
const token_starts = tree.tokens.items(.start);
|
||||
|
||||
const int_token = main_tokens[int_lit];
|
||||
const prefixed_bytes = tree.tokenSlice(int_token);
|
||||
@@ -2972,6 +3167,8 @@ fn floatLiteral(
|
||||
const arena = scope.arena();
|
||||
const tree = scope.tree();
|
||||
const main_tokens = tree.nodes.items(.main_token);
|
||||
const token_starts = tree.tokens.items(.start);
|
||||
|
||||
const main_token = main_tokens[float_lit];
|
||||
const bytes = tree.tokenSlice(main_token);
|
||||
if (bytes.len > 2 and bytes[1] == 'x') {
|
||||
@@ -2988,17 +3185,18 @@ fn floatLiteral(
|
||||
return rvalue(mod, scope, rl, result);
|
||||
}
|
||||
|
||||
fn assembly(mod: *Module, scope: *Scope, rl: ResultLoc, full: ast.full.Asm) InnerError!*zir.Inst {
|
||||
fn asmExpr(mod: *Module, scope: *Scope, rl: ResultLoc, full: ast.full.Asm) InnerError!*zir.Inst {
|
||||
const arena = scope.arena();
|
||||
const tree = scope.tree();
|
||||
const node_datas = tree.nodes.items(.data);
|
||||
const main_tokens = tree.nodes.items(.main_token);
|
||||
const token_starts = tree.tokens.items(.start);
|
||||
const node_datas = tree.nodes.items(.data);
|
||||
|
||||
if (full.outputs.len != 0) {
|
||||
return mod.failTok(scope, full.ast.asm_token, "TODO implement asm with an output", .{});
|
||||
}
|
||||
|
||||
const inputs = try arena.alloc(*zir.Inst, full.inputs.len);
|
||||
const inputs = try arena.alloc([]const u8, full.inputs.len);
|
||||
const args = try arena.alloc(*zir.Inst, full.inputs.len);
|
||||
|
||||
const src = token_starts[full.ast.asm_token];
|
||||
@@ -3010,15 +3208,16 @@ fn assembly(mod: *Module, scope: *Scope, rl: ResultLoc, full: ast.full.Asm) Inne
|
||||
|
||||
for (full.inputs) |input, i| {
|
||||
// TODO semantically analyze constraints
|
||||
inputs[i] = try expr(mod, scope, str_type_rl, input.constraint);
|
||||
args[i] = try expr(mod, scope, .none, input.expr);
|
||||
const constraint_token = main_tokens[input] + 2;
|
||||
inputs[i] = try parseStringLiteral(mod, scope, constraint_token);
|
||||
args[i] = try expr(mod, scope, .none, node_datas[input].lhs);
|
||||
}
|
||||
|
||||
const return_type = try addZIRInstConst(mod, scope, src, .{
|
||||
.ty = Type.initTag(.type),
|
||||
.val = Value.initTag(.void_type),
|
||||
});
|
||||
const asm_inst = try addZIRInst(mod, scope, src, zir.Inst.@"asm", .{
|
||||
const asm_inst = try addZIRInst(mod, scope, src, zir.Inst.Asm, .{
|
||||
.asm_source = try expr(mod, scope, str_type_rl, full.ast.template),
|
||||
.return_type = return_type,
|
||||
}, .{
|
||||
@@ -3185,8 +3384,9 @@ fn builtinCall(
|
||||
params: []const ast.Node.Index,
|
||||
) InnerError!*zir.Inst {
|
||||
const tree = scope.tree();
|
||||
const node_datas = tree.nodes.items(.data);
|
||||
const main_tokens = tree.nodes.items(.main_token);
|
||||
const token_starts = tree.tokens.items(.start);
|
||||
|
||||
const builtin_token = main_tokens[call];
|
||||
const builtin_name = tree.tokenSlice(builtin_token);
|
||||
|
||||
@@ -3200,11 +3400,13 @@ fn builtinCall(
|
||||
builtin_name,
|
||||
});
|
||||
};
|
||||
if (info.param_count != params.len) {
|
||||
const s = if (params.len == 1) "" else "s";
|
||||
return mod.failTok(scope, builtin_token, "expected {d} parameter{s}, found {d}", .{
|
||||
expected, s, found,
|
||||
});
|
||||
if (info.param_count) |expected| {
|
||||
if (expected != params.len) {
|
||||
const s = if (expected == 1) "" else "s";
|
||||
return mod.failTok(scope, builtin_token, "expected {d} parameter{s}, found {d}", .{
|
||||
expected, s, params.len,
|
||||
});
|
||||
}
|
||||
}
|
||||
const src = token_starts[builtin_token];
|
||||
|
||||
@@ -3237,7 +3439,7 @@ fn builtinCall(
|
||||
},
|
||||
.compile_error => {
|
||||
const target = try expr(mod, scope, .none, params[0]);
|
||||
const result = addZIRUnOp(mod, scope, src, .compile_error, target);
|
||||
const result = try addZIRUnOp(mod, scope, src, .compile_error, target);
|
||||
return rvalue(mod, scope, rl, result);
|
||||
},
|
||||
.set_eval_branch_quota => {
|
||||
@@ -3386,8 +3588,9 @@ fn callExpr(
|
||||
}
|
||||
|
||||
const tree = scope.tree();
|
||||
const node_datas = tree.nodes.items(.data);
|
||||
const main_tokens = tree.nodes.items(.main_token);
|
||||
const token_starts = tree.tokens.items(.start);
|
||||
|
||||
const lhs = try expr(mod, scope, .none, call.ast.fn_expr);
|
||||
|
||||
const args = try scope.getGenZIR().arena.alloc(*zir.Inst, call.ast.params.len);
|
||||
@@ -3446,23 +3649,26 @@ fn getSimplePrimitiveValue(name: []const u8) ?TypedValue {
|
||||
return null;
|
||||
}
|
||||
|
||||
fn nodeMayNeedMemoryLocation(start_node: *ast.Node, scope: *Scope) bool {
|
||||
fn nodeMayNeedMemoryLocation(scope: *Scope, start_node: ast.Node.Index) bool {
|
||||
const tree = scope.tree();
|
||||
const node_tags = tree.nodes.items(.tag);
|
||||
const node_datas = tree.nodes.items(.data);
|
||||
const main_tokens = tree.nodes.items(.main_token);
|
||||
const token_tags = tree.tokens.items(.tag);
|
||||
|
||||
var node = start_node;
|
||||
while (true) {
|
||||
switch (node.tag) {
|
||||
.Root,
|
||||
switch (node_tags[node]) {
|
||||
.root,
|
||||
.@"usingnamespace",
|
||||
.test_decl,
|
||||
.doc_comment,
|
||||
.switch_case,
|
||||
.switch_else,
|
||||
.Else,
|
||||
.Payload,
|
||||
.PointerPayload,
|
||||
.PointerIndexPayload,
|
||||
.ContainerField,
|
||||
.ErrorTag,
|
||||
.FieldInitializer,
|
||||
.switch_case_one,
|
||||
.container_field_init,
|
||||
.container_field_align,
|
||||
.container_field,
|
||||
.asm_output,
|
||||
.asm_input,
|
||||
=> unreachable,
|
||||
|
||||
.@"return",
|
||||
@@ -3470,8 +3676,12 @@ fn nodeMayNeedMemoryLocation(start_node: *ast.Node, scope: *Scope) bool {
|
||||
.@"continue",
|
||||
.bit_not,
|
||||
.bool_not,
|
||||
.var_decl,
|
||||
.global_var_decl,
|
||||
.local_var_decl,
|
||||
.simple_var_decl,
|
||||
.aligned_var_decl,
|
||||
.@"defer",
|
||||
.@"errdefer",
|
||||
.address_of,
|
||||
.optional_type,
|
||||
.negation,
|
||||
@@ -3479,27 +3689,46 @@ fn nodeMayNeedMemoryLocation(start_node: *ast.Node, scope: *Scope) bool {
|
||||
.@"resume",
|
||||
.array_type,
|
||||
.array_type_sentinel,
|
||||
.PtrType,
|
||||
.slice_type,
|
||||
.ptr_type_aligned,
|
||||
.ptr_type_sentinel,
|
||||
.ptr_type,
|
||||
.ptr_type_bit_range,
|
||||
.@"suspend",
|
||||
.@"anytype",
|
||||
.error_type,
|
||||
.FnProto,
|
||||
.fn_proto_simple,
|
||||
.fn_proto_multi,
|
||||
.fn_proto_one,
|
||||
.fn_proto,
|
||||
.fn_decl,
|
||||
.anyframe_type,
|
||||
.anyframe_literal,
|
||||
.integer_literal,
|
||||
.float_literal,
|
||||
.enum_literal,
|
||||
.string_literal,
|
||||
.MultilineStringLiteral,
|
||||
.multiline_string_literal,
|
||||
.char_literal,
|
||||
.bool_literal,
|
||||
.true_literal,
|
||||
.false_literal,
|
||||
.null_literal,
|
||||
.undefined_literal,
|
||||
.@"unreachable",
|
||||
.unreachable_literal,
|
||||
.identifier,
|
||||
.error_set_decl,
|
||||
.ContainerDecl,
|
||||
.container_decl,
|
||||
.container_decl_comma,
|
||||
.container_decl_two,
|
||||
.container_decl_two_comma,
|
||||
.container_decl_arg,
|
||||
.container_decl_arg_comma,
|
||||
.tagged_union,
|
||||
.tagged_union_comma,
|
||||
.tagged_union_two,
|
||||
.tagged_union_two_comma,
|
||||
.tagged_union_enum_tag,
|
||||
.tagged_union_enum_tag_comma,
|
||||
.@"asm",
|
||||
.asm_simple,
|
||||
.add,
|
||||
.add_wrap,
|
||||
.array_cat,
|
||||
@@ -3537,14 +3766,16 @@ fn nodeMayNeedMemoryLocation(start_node: *ast.Node, scope: *Scope) bool {
|
||||
.mod,
|
||||
.mul,
|
||||
.mul_wrap,
|
||||
.range,
|
||||
.period,
|
||||
.switch_range,
|
||||
.field_access,
|
||||
.sub,
|
||||
.sub_wrap,
|
||||
.slice,
|
||||
.slice_open,
|
||||
.slice_sentinel,
|
||||
.deref,
|
||||
.array_access,
|
||||
.block,
|
||||
.error_value,
|
||||
.while_simple, // This variant cannot have an else expression.
|
||||
.while_cont, // This variant cannot have an else expression.
|
||||
.for_simple, // This variant cannot have an else expression.
|
||||
@@ -3558,18 +3789,30 @@ fn nodeMayNeedMemoryLocation(start_node: *ast.Node, scope: *Scope) bool {
|
||||
.@"comptime",
|
||||
.@"nosuspend",
|
||||
.unwrap_optional,
|
||||
=> node = datas[node].lhs,
|
||||
=> node = node_datas[node].lhs,
|
||||
|
||||
// Forward the question to the RHS sub-expression.
|
||||
.@"catch",
|
||||
.@"orelse",
|
||||
=> node = datas[node].rhs,
|
||||
=> node = node_datas[node].rhs,
|
||||
|
||||
// True because these are exactly the expressions we need memory locations for.
|
||||
.ArrayInitializer,
|
||||
.ArrayInitializerDot,
|
||||
.StructInitializer,
|
||||
.StructInitializerDot,
|
||||
.array_init_one,
|
||||
.array_init_one_comma,
|
||||
.array_init_dot_two,
|
||||
.array_init_dot_two_comma,
|
||||
.array_init_dot,
|
||||
.array_init_dot_comma,
|
||||
.array_init,
|
||||
.array_init_comma,
|
||||
.struct_init_one,
|
||||
.struct_init_one_comma,
|
||||
.struct_init_dot_two,
|
||||
.struct_init_dot_two_comma,
|
||||
.struct_init_dot,
|
||||
.struct_init_dot_comma,
|
||||
.struct_init,
|
||||
.struct_init_comma,
|
||||
=> return true,
|
||||
|
||||
// True because depending on comptime conditions, sub-expressions
|
||||
@@ -3578,6 +3821,7 @@ fn nodeMayNeedMemoryLocation(start_node: *ast.Node, scope: *Scope) bool {
|
||||
.@"if", // This variant always has an else expression.
|
||||
.@"for", // This variant always has an else expression.
|
||||
.@"switch",
|
||||
.switch_comma,
|
||||
.call_one,
|
||||
.call_one_comma,
|
||||
.async_call_one,
|
||||
@@ -3588,10 +3832,10 @@ fn nodeMayNeedMemoryLocation(start_node: *ast.Node, scope: *Scope) bool {
|
||||
.async_call_comma,
|
||||
=> return true,
|
||||
|
||||
block_two,
|
||||
block_two_semicolon,
|
||||
block,
|
||||
block_semicolon,
|
||||
.block_two,
|
||||
.block_two_semicolon,
|
||||
.block,
|
||||
.block_semicolon,
|
||||
=> {
|
||||
const lbrace = main_tokens[node];
|
||||
if (token_tags[lbrace - 1] == .colon) {
|
||||
@@ -3603,7 +3847,11 @@ fn nodeMayNeedMemoryLocation(start_node: *ast.Node, scope: *Scope) bool {
|
||||
}
|
||||
},
|
||||
|
||||
.builtin_call => {
|
||||
.builtin_call,
|
||||
.builtin_call_comma,
|
||||
.builtin_call_two,
|
||||
.builtin_call_two_comma,
|
||||
=> {
|
||||
const builtin_token = main_tokens[node];
|
||||
const builtin_name = tree.tokenSlice(builtin_token);
|
||||
// If the builtin is an invalid name, we don't cause an error here; instead
|
||||
@@ -3661,7 +3909,6 @@ fn rvalueVoid(
|
||||
result: void,
|
||||
) InnerError!*zir.Inst {
|
||||
const tree = scope.tree();
|
||||
const node_datas = tree.nodes.items(.data);
|
||||
const main_tokens = tree.nodes.items(.main_token);
|
||||
const src = tree.tokens.items(.start)[tree.firstToken(node)];
|
||||
const void_inst = try addZIRInstConst(mod, scope, src, .{
|
||||
@@ -3765,7 +4012,7 @@ pub fn addZirInstT(
|
||||
src: usize,
|
||||
comptime T: type,
|
||||
tag: zir.Inst.Tag,
|
||||
positionals: std.meta.fieldInfo(tag.Type(), .positionals).field_type,
|
||||
positionals: std.meta.fieldInfo(T, .positionals).field_type,
|
||||
) !*T {
|
||||
const gen_zir = scope.getGenZIR();
|
||||
try gen_zir.instructions.ensureCapacity(mod.gpa, gen_zir.instructions.items.len + 1);
|
||||
|
||||
+5
-11
@@ -863,8 +863,8 @@ pub const Inst = struct {
|
||||
kw_args: struct {
|
||||
@"volatile": bool = false,
|
||||
output: ?*Inst = null,
|
||||
inputs: []*Inst = &[0]*Inst{},
|
||||
clobbers: []*Inst = &[0]*Inst{},
|
||||
inputs: []const []const u8 = &.{},
|
||||
clobbers: []const []const u8 = &.{},
|
||||
args: []*Inst = &[0]*Inst{},
|
||||
},
|
||||
};
|
||||
@@ -1192,16 +1192,9 @@ pub const Inst = struct {
|
||||
},
|
||||
kw_args: struct {
|
||||
init_inst: ?*Inst = null,
|
||||
init_kind: InitKind = .none,
|
||||
has_enum_token: bool,
|
||||
layout: std.builtin.TypeInfo.ContainerLayout = .Auto,
|
||||
},
|
||||
|
||||
// TODO error: values of type '(enum literal)' must be comptime known
|
||||
pub const InitKind = enum {
|
||||
enum_type,
|
||||
tag_type,
|
||||
none,
|
||||
};
|
||||
};
|
||||
|
||||
pub const SwitchBr = struct {
|
||||
@@ -1413,6 +1406,7 @@ const Writer = struct {
|
||||
}
|
||||
switch (@TypeOf(param)) {
|
||||
*Inst => return self.writeInstParamToStream(stream, param),
|
||||
?*Inst => return self.writeInstParamToStream(stream, param.?),
|
||||
[]*Inst => {
|
||||
try stream.writeByte('[');
|
||||
for (param) |inst, i| {
|
||||
@@ -1480,7 +1474,7 @@ const Writer = struct {
|
||||
const name = self.loop_table.get(param).?;
|
||||
return stream.print("\"{}\"", .{std.zig.fmtEscapes(name)});
|
||||
},
|
||||
[][]const u8 => {
|
||||
[][]const u8, []const []const u8 => {
|
||||
try stream.writeByte('[');
|
||||
for (param) |str, i| {
|
||||
if (i != 0) {
|
||||
|
||||
+7
-5
@@ -2023,19 +2023,21 @@ fn zirDeref(mod: *Module, scope: *Scope, deref: *zir.Inst.UnOp) InnerError!*Inst
|
||||
fn zirAsm(mod: *Module, scope: *Scope, assembly: *zir.Inst.Asm) InnerError!*Inst {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
const return_type = try resolveType(mod, scope, assembly.positionals.return_type);
|
||||
const asm_source = try resolveConstString(mod, scope, assembly.positionals.asm_source);
|
||||
const output = if (assembly.kw_args.output) |o| try resolveConstString(mod, scope, o) else null;
|
||||
|
||||
const inputs = try scope.arena().alloc([]const u8, assembly.kw_args.inputs.len);
|
||||
const clobbers = try scope.arena().alloc([]const u8, assembly.kw_args.clobbers.len);
|
||||
const args = try scope.arena().alloc(*Inst, assembly.kw_args.args.len);
|
||||
const arena = scope.arena();
|
||||
const inputs = try arena.alloc([]const u8, assembly.kw_args.inputs.len);
|
||||
const clobbers = try arena.alloc([]const u8, assembly.kw_args.clobbers.len);
|
||||
const args = try arena.alloc(*Inst, assembly.kw_args.args.len);
|
||||
|
||||
for (inputs) |*elem, i| {
|
||||
elem.* = try resolveConstString(mod, scope, assembly.kw_args.inputs[i]);
|
||||
elem.* = try arena.dupe(u8, assembly.kw_args.inputs[i]);
|
||||
}
|
||||
for (clobbers) |*elem, i| {
|
||||
elem.* = try resolveConstString(mod, scope, assembly.kw_args.clobbers[i]);
|
||||
elem.* = try arena.dupe(u8, assembly.kw_args.clobbers[i]);
|
||||
}
|
||||
for (args) |*elem, i| {
|
||||
const arg = try resolveInst(mod, scope, assembly.kw_args.args[i]);
|
||||
|
||||
Reference in New Issue
Block a user