mirror of
https://github.com/ziglang/zig.git
synced 2025-12-16 11:13:08 +00:00
Sema: implement function declarations
This commit is contained in:
parent
fb95fd8443
commit
db7acd83d2
14
BRANCH_TODO
14
BRANCH_TODO
@ -274,17 +274,3 @@ pub fn analyzeNamespace(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const is_inline = decl_tv.ty.fnCallingConvention() == .Inline;
|
|
||||||
const anal_state: Fn.Analysis = if (is_inline) .inline_only else .queued;
|
|
||||||
|
|
||||||
new_func.* = .{
|
|
||||||
.state = anal_state,
|
|
||||||
.zir = fn_zir,
|
|
||||||
.body = undefined,
|
|
||||||
.owner_decl = decl,
|
|
||||||
};
|
|
||||||
fn_payload.* = .{
|
|
||||||
.base = .{ .tag = .function },
|
|
||||||
.data = new_func,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|||||||
@ -565,6 +565,11 @@ pub const EnumFull = struct {
|
|||||||
/// the `Decl` only, with a `Value` tag of `extern_fn`.
|
/// the `Decl` only, with a `Value` tag of `extern_fn`.
|
||||||
pub const Fn = struct {
|
pub const Fn = struct {
|
||||||
owner_decl: *Decl,
|
owner_decl: *Decl,
|
||||||
|
/// The ZIR instruction that is a function instruction. Use this to find
|
||||||
|
/// the body. We store this rather than the body directly so that when ZIR
|
||||||
|
/// is regenerated on update(), we can map this to the new corresponding
|
||||||
|
/// ZIR instruction.
|
||||||
|
zir_body_inst: Zir.Inst.Index,
|
||||||
/// undefined unless analysis state is `success`.
|
/// undefined unless analysis state is `success`.
|
||||||
body: ir.Body,
|
body: ir.Body,
|
||||||
state: Analysis,
|
state: Analysis,
|
||||||
|
|||||||
59
src/Sema.zig
59
src/Sema.zig
@ -478,7 +478,7 @@ fn zirExtended(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerErro
|
|||||||
const extended = sema.code.instructions.items(.data)[inst].extended;
|
const extended = sema.code.instructions.items(.data)[inst].extended;
|
||||||
switch (extended.opcode) {
|
switch (extended.opcode) {
|
||||||
// zig fmt: off
|
// zig fmt: off
|
||||||
.func => return sema.zirFuncExtended( block, extended),
|
.func => return sema.zirFuncExtended( block, extended, inst),
|
||||||
.variable => return sema.zirVarExtended( block, extended),
|
.variable => return sema.zirVarExtended( block, extended),
|
||||||
.ret_ptr => return sema.zirRetPtr( block, extended),
|
.ret_ptr => return sema.zirRetPtr( block, extended),
|
||||||
.ret_type => return sema.zirRetType( block, extended),
|
.ret_type => return sema.zirRetType( block, extended),
|
||||||
@ -2747,13 +2747,13 @@ fn zirFunc(
|
|||||||
const src = inst_data.src();
|
const src = inst_data.src();
|
||||||
const extra = sema.code.extraData(Zir.Inst.Func, inst_data.payload_index);
|
const extra = sema.code.extraData(Zir.Inst.Func, inst_data.payload_index);
|
||||||
const param_types = sema.code.refSlice(extra.end, extra.data.param_types_len);
|
const param_types = sema.code.refSlice(extra.end, extra.data.param_types_len);
|
||||||
const body = sema.code.extra[extra.end + param_types.len ..][0..extra.data.body_len];
|
const body_inst = if (extra.data.body_len != 0) inst else 0;
|
||||||
|
|
||||||
return sema.funcCommon(
|
return sema.funcCommon(
|
||||||
block,
|
block,
|
||||||
inst_data.src_node,
|
inst_data.src_node,
|
||||||
param_types,
|
param_types,
|
||||||
body,
|
body_inst,
|
||||||
extra.data.return_type,
|
extra.data.return_type,
|
||||||
.Unspecified,
|
.Unspecified,
|
||||||
Value.initTag(.null_value),
|
Value.initTag(.null_value),
|
||||||
@ -2767,7 +2767,7 @@ fn funcCommon(
|
|||||||
block: *Scope.Block,
|
block: *Scope.Block,
|
||||||
src_node_offset: i32,
|
src_node_offset: i32,
|
||||||
zir_param_types: []const Zir.Inst.Ref,
|
zir_param_types: []const Zir.Inst.Ref,
|
||||||
body: []const Zir.Inst.Index,
|
body_inst: Zir.Inst.Index,
|
||||||
zir_return_type: Zir.Inst.Ref,
|
zir_return_type: Zir.Inst.Ref,
|
||||||
cc: std.builtin.CallingConvention,
|
cc: std.builtin.CallingConvention,
|
||||||
align_val: Value,
|
align_val: Value,
|
||||||
@ -2778,26 +2778,23 @@ fn funcCommon(
|
|||||||
const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = src_node_offset };
|
const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = src_node_offset };
|
||||||
const return_type = try sema.resolveType(block, ret_ty_src, zir_return_type);
|
const return_type = try sema.resolveType(block, ret_ty_src, zir_return_type);
|
||||||
|
|
||||||
if (body.len == 0) {
|
const fn_ty: Type = fn_ty: {
|
||||||
return sema.mod.fail(&block.base, src, "TODO: Sema: implement func with body", .{});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hot path for some common function types.
|
// Hot path for some common function types.
|
||||||
if (zir_param_types.len == 0 and !var_args and align_val.tag() == .null_value) {
|
if (zir_param_types.len == 0 and !var_args and align_val.tag() == .null_value) {
|
||||||
if (return_type.zigTypeTag() == .NoReturn and cc == .Unspecified) {
|
if (return_type.zigTypeTag() == .NoReturn and cc == .Unspecified) {
|
||||||
return sema.mod.constType(sema.arena, src, Type.initTag(.fn_noreturn_no_args));
|
break :fn_ty Type.initTag(.fn_noreturn_no_args);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (return_type.zigTypeTag() == .Void and cc == .Unspecified) {
|
if (return_type.zigTypeTag() == .Void and cc == .Unspecified) {
|
||||||
return sema.mod.constType(sema.arena, src, Type.initTag(.fn_void_no_args));
|
break :fn_ty Type.initTag(.fn_void_no_args);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (return_type.zigTypeTag() == .NoReturn and cc == .Naked) {
|
if (return_type.zigTypeTag() == .NoReturn and cc == .Naked) {
|
||||||
return sema.mod.constType(sema.arena, src, Type.initTag(.fn_naked_noreturn_no_args));
|
break :fn_ty Type.initTag(.fn_naked_noreturn_no_args);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (return_type.zigTypeTag() == .Void and cc == .C) {
|
if (return_type.zigTypeTag() == .Void and cc == .C) {
|
||||||
return sema.mod.constType(sema.arena, src, Type.initTag(.fn_ccc_void_no_args));
|
break :fn_ty Type.initTag(.fn_ccc_void_no_args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2814,15 +2811,46 @@ fn funcCommon(
|
|||||||
return sema.mod.fail(&block.base, src, "TODO implement support for function prototypes to have alignment specified", .{});
|
return sema.mod.fail(&block.base, src, "TODO implement support for function prototypes to have alignment specified", .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
const fn_ty = try Type.Tag.function.create(sema.arena, .{
|
break :fn_ty try Type.Tag.function.create(sema.arena, .{
|
||||||
.param_types = param_types,
|
.param_types = param_types,
|
||||||
.return_type = return_type,
|
.return_type = return_type,
|
||||||
.cc = cc,
|
.cc = cc,
|
||||||
.is_var_args = var_args,
|
.is_var_args = var_args,
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
if (body_inst == 0) {
|
||||||
return sema.mod.constType(sema.arena, src, fn_ty);
|
return sema.mod.constType(sema.arena, src, fn_ty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const is_inline = fn_ty.fnCallingConvention() == .Inline;
|
||||||
|
const anal_state: Module.Fn.Analysis = if (is_inline) .inline_only else .queued;
|
||||||
|
|
||||||
|
// Use the Decl's arena for function memory.
|
||||||
|
var fn_arena = std.heap.ArenaAllocator.init(sema.gpa);
|
||||||
|
errdefer fn_arena.deinit();
|
||||||
|
|
||||||
|
const new_func = try fn_arena.allocator.create(Module.Fn);
|
||||||
|
const fn_payload = try fn_arena.allocator.create(Value.Payload.Function);
|
||||||
|
|
||||||
|
new_func.* = .{
|
||||||
|
.state = anal_state,
|
||||||
|
.zir_body_inst = body_inst,
|
||||||
|
.owner_decl = sema.owner_decl,
|
||||||
|
.body = undefined,
|
||||||
|
};
|
||||||
|
fn_payload.* = .{
|
||||||
|
.base = .{ .tag = .function },
|
||||||
|
.data = new_func,
|
||||||
|
};
|
||||||
|
const result = try sema.mod.constInst(sema.arena, src, .{
|
||||||
|
.ty = fn_ty,
|
||||||
|
.val = Value.initPayload(&fn_payload.base),
|
||||||
|
});
|
||||||
|
try sema.owner_decl.finalizeNewArena(&fn_arena);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
fn zirAs(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
|
fn zirAs(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
|
||||||
const tracy = trace(@src());
|
const tracy = trace(@src());
|
||||||
defer tracy.end();
|
defer tracy.end();
|
||||||
@ -5461,6 +5489,7 @@ fn zirFuncExtended(
|
|||||||
sema: *Sema,
|
sema: *Sema,
|
||||||
block: *Scope.Block,
|
block: *Scope.Block,
|
||||||
extended: Zir.Inst.Extended.InstData,
|
extended: Zir.Inst.Extended.InstData,
|
||||||
|
inst: Zir.Inst.Index,
|
||||||
) InnerError!*Inst {
|
) InnerError!*Inst {
|
||||||
const tracy = trace(@src());
|
const tracy = trace(@src());
|
||||||
defer tracy.end();
|
defer tracy.end();
|
||||||
@ -5502,13 +5531,13 @@ fn zirFuncExtended(
|
|||||||
const param_types = sema.code.refSlice(extra_index, extra.data.param_types_len);
|
const param_types = sema.code.refSlice(extra_index, extra.data.param_types_len);
|
||||||
extra_index += param_types.len;
|
extra_index += param_types.len;
|
||||||
|
|
||||||
const body = sema.code.extra[extra_index..][0..extra.data.body_len];
|
const body_inst = if (extra.data.body_len != 0) inst else 0;
|
||||||
|
|
||||||
return sema.funcCommon(
|
return sema.funcCommon(
|
||||||
block,
|
block,
|
||||||
extra.data.src_node,
|
extra.data.src_node,
|
||||||
param_types,
|
param_types,
|
||||||
body,
|
body_inst,
|
||||||
extra.data.return_type,
|
extra.data.return_type,
|
||||||
cc,
|
cc,
|
||||||
align_val,
|
align_val,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user