mirror of
https://github.com/ziglang/zig.git
synced 2026-02-13 04:48:20 +00:00
astgen: implement function calls
This commit is contained in:
parent
907142a036
commit
50010447bd
@ -237,12 +237,20 @@ pub const Decl = struct {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn tokSrcLoc(decl: *Decl, token_index: ast.TokenIndex) LazySrcLoc {
|
||||
pub fn relativeToNodeIndex(decl: Decl, offset: i32) ast.Node.Index {
|
||||
return @bitCast(ast.Node.Index, offset + @bitCast(i32, decl.srcNode()));
|
||||
}
|
||||
|
||||
pub fn nodeIndexToRelative(decl: Decl, node_index: ast.Node.Index) i32 {
|
||||
return @bitCast(i32, node_index) - @bitCast(i32, decl.srcNode());
|
||||
}
|
||||
|
||||
pub fn tokSrcLoc(decl: Decl, token_index: ast.TokenIndex) LazySrcLoc {
|
||||
return .{ .token_offset = token_index - decl.srcToken() };
|
||||
}
|
||||
|
||||
pub fn nodeSrcLoc(decl: *Decl, node_index: ast.Node.Index) LazySrcLoc {
|
||||
return .{ .node_offset = node_index - decl.srcNode() };
|
||||
pub fn nodeSrcLoc(decl: Decl, node_index: ast.Node.Index) LazySrcLoc {
|
||||
return .{ .node_offset = decl.nodeIndexToRelative(node_index) };
|
||||
}
|
||||
|
||||
pub fn srcLoc(decl: *Decl) SrcLoc {
|
||||
@ -1076,6 +1084,40 @@ pub const Scope = struct {
|
||||
return new_index + gz.zir_code.ref_start_index;
|
||||
}
|
||||
|
||||
pub fn addCall(
|
||||
gz: *GenZir,
|
||||
tag: zir.Inst.Tag,
|
||||
callee: zir.Inst.Ref,
|
||||
args: []const zir.Inst.Ref,
|
||||
/// Absolute node index. This function does the conversion to offset from Decl.
|
||||
abs_node_index: ast.Node.Index,
|
||||
) !zir.Inst.Index {
|
||||
assert(callee != 0);
|
||||
assert(abs_node_index != 0);
|
||||
const gpa = gz.zir_code.gpa;
|
||||
try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);
|
||||
try gz.zir_code.instructions.ensureCapacity(gpa, gz.zir_code.instructions.len + 1);
|
||||
try gz.zir_code.extra.ensureCapacity(gpa, gz.zir_code.extra.items.len +
|
||||
@typeInfo(zir.Inst.Call).Struct.fields.len + args.len);
|
||||
|
||||
const payload_index = gz.zir_code.addExtra(zir.Inst.Call{
|
||||
.callee = callee,
|
||||
.args_len = @intCast(u32, args.len),
|
||||
}) catch unreachable; // Capacity is ensured above.
|
||||
gz.zir_code.extra.appendSliceAssumeCapacity(args);
|
||||
|
||||
const new_index = @intCast(zir.Inst.Index, gz.zir_code.instructions.len);
|
||||
gz.zir_code.instructions.appendAssumeCapacity(.{
|
||||
.tag = tag,
|
||||
.data = .{ .pl_node = .{
|
||||
.src_node = gz.zir_code.decl.nodeIndexToRelative(abs_node_index),
|
||||
.payload_index = payload_index,
|
||||
} },
|
||||
});
|
||||
gz.instructions.appendAssumeCapacity(new_index);
|
||||
return new_index + gz.zir_code.ref_start_index;
|
||||
}
|
||||
|
||||
pub fn addInt(gz: *GenZir, integer: u64) !zir.Inst.Ref {
|
||||
return gz.add(.{
|
||||
.tag = .int,
|
||||
@ -1095,7 +1137,7 @@ pub const Scope = struct {
|
||||
.tag = tag,
|
||||
.data = .{ .un_node = .{
|
||||
.operand = operand,
|
||||
.src_node = abs_node_index - gz.zir_code.decl.srcNode(),
|
||||
.src_node = gz.zir_code.decl.nodeIndexToRelative(abs_node_index),
|
||||
} },
|
||||
});
|
||||
}
|
||||
@ -1116,7 +1158,7 @@ pub const Scope = struct {
|
||||
gz.zir_code.instructions.appendAssumeCapacity(.{
|
||||
.tag = tag,
|
||||
.data = .{ .pl_node = .{
|
||||
.src_node = gz.zir_code.decl.srcNode() - abs_node_index,
|
||||
.src_node = gz.zir_code.decl.nodeIndexToRelative(abs_node_index),
|
||||
.payload_index = payload_index,
|
||||
} },
|
||||
});
|
||||
@ -1177,7 +1219,7 @@ pub const Scope = struct {
|
||||
) !zir.Inst.Ref {
|
||||
return gz.add(.{
|
||||
.tag = tag,
|
||||
.data = .{ .node = abs_node_index - gz.zir_code.decl.srcNode() },
|
||||
.data = .{ .node = gz.zir_code.decl.nodeIndexToRelative(abs_node_index) },
|
||||
});
|
||||
}
|
||||
|
||||
@ -1205,14 +1247,14 @@ pub const Scope = struct {
|
||||
try gz.zir_code.instructions.append(gz.zir_code.gpa, .{
|
||||
.tag = tag,
|
||||
.data = .{ .pl_node = .{
|
||||
.src_node = node - gz.zir_code.decl.srcNode(),
|
||||
.src_node = gz.zir_code.decl.nodeIndexToRelative(node),
|
||||
.payload_index = undefined,
|
||||
} },
|
||||
});
|
||||
return new_index;
|
||||
}
|
||||
|
||||
fn add(gz: *GenZir, inst: zir.Inst) !zir.Inst.Ref {
|
||||
pub fn add(gz: *GenZir, inst: zir.Inst) !zir.Inst.Ref {
|
||||
const gpa = gz.zir_code.gpa;
|
||||
try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);
|
||||
try gz.zir_code.instructions.ensureCapacity(gpa, gz.zir_code.instructions.len + 1);
|
||||
@ -1593,7 +1635,7 @@ pub const SrcLoc = struct {
|
||||
},
|
||||
.node_offset => |node_off| {
|
||||
const decl = src_loc.container.decl;
|
||||
const node_index = decl.srcNode() + node_off;
|
||||
const node_index = decl.relativeToNodeIndex(node_off);
|
||||
const tree = decl.container.file_scope.base.tree();
|
||||
const tok_index = tree.firstToken(node_index);
|
||||
const token_starts = tree.tokens.items(.start);
|
||||
@ -1659,84 +1701,84 @@ pub const LazySrcLoc = union(enum) {
|
||||
/// The source location points to an AST node, which is this value offset
|
||||
/// from its containing Decl node AST index.
|
||||
/// The Decl is determined contextually.
|
||||
node_offset: u32,
|
||||
node_offset: i32,
|
||||
/// The source location points to a variable declaration type expression,
|
||||
/// found by taking this AST node index offset from the containing
|
||||
/// Decl AST node, which points to a variable declaration AST node. Next, navigate
|
||||
/// to the type expression.
|
||||
/// The Decl is determined contextually.
|
||||
node_offset_var_decl_ty: u32,
|
||||
node_offset_var_decl_ty: i32,
|
||||
/// The source location points to a for loop condition expression,
|
||||
/// found by taking this AST node index offset from the containing
|
||||
/// Decl AST node, which points to a for loop AST node. Next, navigate
|
||||
/// to the condition expression.
|
||||
/// The Decl is determined contextually.
|
||||
node_offset_for_cond: u32,
|
||||
node_offset_for_cond: i32,
|
||||
/// The source location points to the first parameter of a builtin
|
||||
/// function call, found by taking this AST node index offset from the containing
|
||||
/// Decl AST node, which points to a builtin call AST node. Next, navigate
|
||||
/// to the first parameter.
|
||||
/// The Decl is determined contextually.
|
||||
node_offset_builtin_call_arg0: u32,
|
||||
node_offset_builtin_call_arg0: i32,
|
||||
/// Same as `node_offset_builtin_call_arg0` except arg index 1.
|
||||
node_offset_builtin_call_arg1: u32,
|
||||
node_offset_builtin_call_arg1: i32,
|
||||
/// Same as `node_offset_builtin_call_arg0` except the arg index is contextually
|
||||
/// determined.
|
||||
node_offset_builtin_call_argn: u32,
|
||||
node_offset_builtin_call_argn: i32,
|
||||
/// The source location points to the index expression of an array access
|
||||
/// expression, found by taking this AST node index offset from the containing
|
||||
/// Decl AST node, which points to an array access AST node. Next, navigate
|
||||
/// to the index expression.
|
||||
/// The Decl is determined contextually.
|
||||
node_offset_array_access_index: u32,
|
||||
node_offset_array_access_index: i32,
|
||||
/// The source location points to the sentinel expression of a slice
|
||||
/// expression, found by taking this AST node index offset from the containing
|
||||
/// Decl AST node, which points to a slice AST node. Next, navigate
|
||||
/// to the sentinel expression.
|
||||
/// The Decl is determined contextually.
|
||||
node_offset_slice_sentinel: u32,
|
||||
node_offset_slice_sentinel: i32,
|
||||
/// The source location points to the callee expression of a function
|
||||
/// call expression, found by taking this AST node index offset from the containing
|
||||
/// Decl AST node, which points to a function call AST node. Next, navigate
|
||||
/// to the callee expression.
|
||||
/// The Decl is determined contextually.
|
||||
node_offset_call_func: u32,
|
||||
node_offset_call_func: i32,
|
||||
/// The source location points to the field name of a field access expression,
|
||||
/// found by taking this AST node index offset from the containing
|
||||
/// Decl AST node, which points to a field access AST node. Next, navigate
|
||||
/// to the field name token.
|
||||
/// The Decl is determined contextually.
|
||||
node_offset_field_name: u32,
|
||||
node_offset_field_name: i32,
|
||||
/// The source location points to the pointer of a pointer deref expression,
|
||||
/// found by taking this AST node index offset from the containing
|
||||
/// Decl AST node, which points to a pointer deref AST node. Next, navigate
|
||||
/// to the pointer expression.
|
||||
/// The Decl is determined contextually.
|
||||
node_offset_deref_ptr: u32,
|
||||
node_offset_deref_ptr: i32,
|
||||
/// The source location points to the assembly source code of an inline assembly
|
||||
/// expression, found by taking this AST node index offset from the containing
|
||||
/// Decl AST node, which points to inline assembly AST node. Next, navigate
|
||||
/// to the asm template source code.
|
||||
/// The Decl is determined contextually.
|
||||
node_offset_asm_source: u32,
|
||||
node_offset_asm_source: i32,
|
||||
/// The source location points to the return type of an inline assembly
|
||||
/// expression, found by taking this AST node index offset from the containing
|
||||
/// Decl AST node, which points to inline assembly AST node. Next, navigate
|
||||
/// to the return type expression.
|
||||
/// The Decl is determined contextually.
|
||||
node_offset_asm_ret_ty: u32,
|
||||
node_offset_asm_ret_ty: i32,
|
||||
/// The source location points to the condition expression of an if
|
||||
/// expression, found by taking this AST node index offset from the containing
|
||||
/// Decl AST node, which points to an if expression AST node. Next, navigate
|
||||
/// to the condition expression.
|
||||
/// The Decl is determined contextually.
|
||||
node_offset_if_cond: u32,
|
||||
node_offset_if_cond: i32,
|
||||
/// The source location points to the type expression of an `anyframe->T`
|
||||
/// expression, found by taking this AST node index offset from the containing
|
||||
/// Decl AST node, which points to a `anyframe->T` expression AST node. Next, navigate
|
||||
/// to the type expression.
|
||||
/// The Decl is determined contextually.
|
||||
node_offset_anyframe_type: u32,
|
||||
node_offset_anyframe_type: i32,
|
||||
|
||||
/// Upgrade to a `SrcLoc` based on the `Decl` or file in the provided scope.
|
||||
pub fn toSrcLoc(lazy: LazySrcLoc, scope: *Scope) SrcLoc {
|
||||
@ -3678,8 +3720,7 @@ pub fn failTok(
|
||||
comptime format: []const u8,
|
||||
args: anytype,
|
||||
) InnerError {
|
||||
const decl_token = scope.srcDecl().?.srcToken();
|
||||
const src: LazySrcLoc = .{ .token_offset = token_index - decl_token };
|
||||
const src = scope.srcDecl().?.tokSrcLoc(token_index);
|
||||
return mod.fail(scope, src, format, args);
|
||||
}
|
||||
|
||||
@ -3692,8 +3733,7 @@ pub fn failNode(
|
||||
comptime format: []const u8,
|
||||
args: anytype,
|
||||
) InnerError {
|
||||
const decl_node = scope.srcDecl().?.srcNode();
|
||||
const src: LazySrcLoc = .{ .node_offset = decl_node - node_index };
|
||||
const src = scope.srcDecl().?.nodeSrcLoc(node_index);
|
||||
return mod.fail(scope, src, format, args);
|
||||
}
|
||||
|
||||
|
||||
@ -618,7 +618,7 @@ fn zirParamType(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerErr
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
const src: LazySrcLoc = .todo;
|
||||
const src: LazySrcLoc = .unneeded;
|
||||
const inst_data = sema.code.instructions.items(.data)[inst].param_type;
|
||||
const fn_inst = try sema.resolveInst(inst_data.callee);
|
||||
const param_index = inst_data.param_index;
|
||||
|
||||
@ -3402,10 +3402,6 @@ fn callExpr(
|
||||
node: ast.Node.Index,
|
||||
call: ast.full.Call,
|
||||
) InnerError!zir.Inst.Ref {
|
||||
if (true) {
|
||||
@panic("TODO update for zir-memory-layout branch");
|
||||
}
|
||||
|
||||
if (call.async_token) |async_token| {
|
||||
return mod.failTok(scope, async_token, "TODO implement async fn call", .{});
|
||||
}
|
||||
@ -3414,11 +3410,14 @@ fn callExpr(
|
||||
const args = try mod.gpa.alloc(zir.Inst.Index, call.ast.params.len);
|
||||
defer mod.gpa.free(args);
|
||||
|
||||
const gen_zir = scope.getGenZir();
|
||||
const gz = scope.getGenZir();
|
||||
for (call.ast.params) |param_node, i| {
|
||||
const param_type = try gen_zir.addParamType(.{
|
||||
.callee = lhs,
|
||||
.param_index = i,
|
||||
const param_type = try gz.add(.{
|
||||
.tag = .param_type,
|
||||
.data = .{ .param_type = .{
|
||||
.callee = lhs,
|
||||
.param_index = @intCast(u32, i),
|
||||
} },
|
||||
});
|
||||
args[i] = try expr(mod, scope, .{ .ty = param_type }, param_node);
|
||||
}
|
||||
@ -3430,7 +3429,7 @@ fn callExpr(
|
||||
const result: zir.Inst.Index = res: {
|
||||
const tag: zir.Inst.Tag = switch (modifier) {
|
||||
.auto => switch (args.len == 0) {
|
||||
true => break :res try gen_zir.addCallNone(lhs, node),
|
||||
true => break :res try gz.addUnNode(.call_none, lhs, node),
|
||||
false => .call,
|
||||
},
|
||||
.async_kw => .call_async_kw,
|
||||
@ -3441,9 +3440,9 @@ fn callExpr(
|
||||
.always_inline => unreachable,
|
||||
.compile_time => .call_compile_time,
|
||||
};
|
||||
break :res try gen_zir.addCall(tag, lhs, args, node);
|
||||
break :res try gz.addCall(tag, lhs, args, node);
|
||||
};
|
||||
return rvalue(mod, scope, rl, result); // TODO function call with result location
|
||||
return rvalue(mod, scope, rl, result, node); // TODO function call with result location
|
||||
}
|
||||
|
||||
fn suspendExpr(mod: *Module, scope: *Scope, node: ast.Node.Index) InnerError!zir.Inst.Ref {
|
||||
|
||||
23
src/zir.zig
23
src/zir.zig
@ -1019,7 +1019,7 @@ pub const Inst = struct {
|
||||
/// Used for unary operators, with an AST node source location.
|
||||
un_node: struct {
|
||||
/// Offset from Decl AST node index.
|
||||
src_node: ast.Node.Index,
|
||||
src_node: i32,
|
||||
/// The meaning of this operand depends on the corresponding `Tag`.
|
||||
operand: Ref,
|
||||
|
||||
@ -1041,7 +1041,7 @@ pub const Inst = struct {
|
||||
pl_node: struct {
|
||||
/// Offset from Decl AST node index.
|
||||
/// `Tag` determines which kind of AST node this points to.
|
||||
src_node: ast.Node.Index,
|
||||
src_node: i32,
|
||||
/// index into extra.
|
||||
/// `Tag` determines what lives there.
|
||||
payload_index: u32,
|
||||
@ -1092,7 +1092,7 @@ pub const Inst = struct {
|
||||
/// Offset from Decl AST token index.
|
||||
tok: ast.TokenIndex,
|
||||
/// Offset from Decl AST node index.
|
||||
node: ast.Node.Index,
|
||||
node: i32,
|
||||
int: u64,
|
||||
array_type_sentinel: struct {
|
||||
len: Ref,
|
||||
@ -1400,9 +1400,10 @@ const Writer = struct {
|
||||
.slice_sentinel,
|
||||
.typeof_peer,
|
||||
.suspend_block,
|
||||
.as_node,
|
||||
=> try self.writePlNode(stream, inst),
|
||||
|
||||
.as_node => try self.writeAs(stream, inst),
|
||||
|
||||
.breakpoint,
|
||||
.dbg_stmt_node,
|
||||
.ret_ptr,
|
||||
@ -1544,6 +1545,16 @@ const Writer = struct {
|
||||
try self.writeSrc(stream, inst_data.src());
|
||||
}
|
||||
|
||||
fn writeAs(self: *Writer, stream: anytype, inst: Inst.Index) !void {
|
||||
const inst_data = self.code.instructions.items(.data)[inst].pl_node;
|
||||
const extra = self.code.extraData(Inst.As, inst_data.payload_index).data;
|
||||
try self.writeInstRef(stream, extra.dest_type);
|
||||
try stream.writeAll(", ");
|
||||
try self.writeInstRef(stream, extra.operand);
|
||||
try stream.writeAll(") ");
|
||||
try self.writeSrc(stream, inst_data.src());
|
||||
}
|
||||
|
||||
fn writeNode(
|
||||
self: *Writer,
|
||||
stream: anytype,
|
||||
@ -1560,8 +1571,8 @@ const Writer = struct {
|
||||
stream: anytype,
|
||||
inst: Inst.Index,
|
||||
) (@TypeOf(stream).Error || error{OutOfMemory})!void {
|
||||
const inst_data = self.code.instructions.items(.data)[inst].decl;
|
||||
try stream.writeAll("TODO)");
|
||||
const decl = self.code.instructions.items(.data)[inst].decl;
|
||||
try stream.print("{s})", .{decl.name});
|
||||
}
|
||||
|
||||
fn writeStrTok(
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user