ZIR: implement return instruction
parent
6b0f7de247
commit
28729efe29
|
@ -62,6 +62,7 @@ pub const Int = struct {
|
|||
|
||||
/// Hint: use `calcLimbLen` to figure out how big an array to allocate for `limbs`.
|
||||
pub fn initSetFixed(limbs: []Limb, value: var) Int {
|
||||
mem.set(Limb, limbs, 0);
|
||||
var s = Int.initFixed(limbs);
|
||||
s.set(value) catch unreachable;
|
||||
return s;
|
||||
|
@ -126,11 +127,10 @@ pub const Int = struct {
|
|||
/// sufficient capacity, the exact amount will be allocated. This occurs even if the requested
|
||||
/// capacity is only greater than the current capacity by one limb.
|
||||
pub fn ensureCapacity(self: *Int, capacity: usize) !void {
|
||||
self.assertWritable();
|
||||
if (capacity <= self.limbs.len) {
|
||||
return;
|
||||
}
|
||||
|
||||
self.assertWritable();
|
||||
self.limbs = try self.allocator.?.realloc(self.limbs, capacity);
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ pub const Inst = struct {
|
|||
|
||||
pub const Tag = enum {
|
||||
unreach,
|
||||
ret,
|
||||
constant,
|
||||
assembly,
|
||||
ptrtoint,
|
||||
|
@ -58,6 +59,12 @@ pub const Inst = struct {
|
|||
args: void,
|
||||
};
|
||||
|
||||
pub const Ret = struct {
|
||||
pub const base_tag = Tag.ret;
|
||||
base: Inst,
|
||||
args: void,
|
||||
};
|
||||
|
||||
pub const Constant = struct {
|
||||
pub const base_tag = Tag.constant;
|
||||
base: Inst,
|
||||
|
@ -491,6 +498,7 @@ const Analyze = struct {
|
|||
.as => return self.analyzeInstAs(block, old_inst.cast(text.Inst.As).?),
|
||||
.@"asm" => return self.analyzeInstAsm(block, old_inst.cast(text.Inst.Asm).?),
|
||||
.@"unreachable" => return self.analyzeInstUnreachable(block, old_inst.cast(text.Inst.Unreachable).?),
|
||||
.@"return" => return self.analyzeInstRet(block, old_inst.cast(text.Inst.Return).?),
|
||||
.@"fn" => return self.analyzeInstFn(block, old_inst.cast(text.Inst.Fn).?),
|
||||
.@"export" => {
|
||||
try self.analyzeExport(block, old_inst.cast(text.Inst.Export).?);
|
||||
|
@ -556,6 +564,13 @@ const Analyze = struct {
|
|||
return self.constType(fntype.base.src, Type.initTag(.fn_naked_noreturn_no_args));
|
||||
}
|
||||
|
||||
if (return_type.zigTypeTag() == .Void and
|
||||
fntype.positionals.param_types.len == 0 and
|
||||
fntype.kw_args.cc == .C)
|
||||
{
|
||||
return self.constType(fntype.base.src, Type.initTag(.fn_ccc_void_no_args));
|
||||
}
|
||||
|
||||
return self.fail(fntype.base.src, "TODO implement fntype instruction more", .{});
|
||||
}
|
||||
|
||||
|
@ -886,6 +901,11 @@ const Analyze = struct {
|
|||
return self.addNewInstArgs(b, unreach.base.src, Type.initTag(.noreturn), Inst.Unreach, {});
|
||||
}
|
||||
|
||||
fn analyzeInstRet(self: *Analyze, block: ?*Block, inst: *text.Inst.Return) InnerError!*Inst {
|
||||
const b = try self.requireRuntimeBlock(block, inst.base.src);
|
||||
return self.addNewInstArgs(b, inst.base.src, Type.initTag(.noreturn), Inst.Ret, {});
|
||||
}
|
||||
|
||||
fn analyzeBody(self: *Analyze, block: ?*Block, body: text.Module.Body) !void {
|
||||
for (body.instructions) |src_inst| {
|
||||
const new_inst = self.analyzeInst(block, src_inst) catch |err| {
|
||||
|
@ -1199,11 +1219,13 @@ pub fn main() anyerror!void {
|
|||
const allocator = if (std.builtin.link_libc) std.heap.c_allocator else &arena.allocator;
|
||||
|
||||
const args = try std.process.argsAlloc(allocator);
|
||||
defer std.process.argsFree(allocator, args);
|
||||
|
||||
const src_path = args[1];
|
||||
const debug_error_trace = true;
|
||||
|
||||
const source = try std.fs.cwd().readFileAllocOptions(allocator, src_path, std.math.maxInt(u32), 1, 0);
|
||||
defer allocator.free(source);
|
||||
|
||||
var zir_module = try text.parse(allocator, source);
|
||||
defer zir_module.deinit(allocator);
|
||||
|
|
|
@ -26,6 +26,7 @@ pub const Inst = struct {
|
|||
as,
|
||||
@"asm",
|
||||
@"unreachable",
|
||||
@"return",
|
||||
@"fn",
|
||||
@"export",
|
||||
primitive,
|
||||
|
@ -50,6 +51,7 @@ pub const Inst = struct {
|
|||
.as => As,
|
||||
.@"asm" => Asm,
|
||||
.@"unreachable" => Unreachable,
|
||||
.@"return" => Return,
|
||||
.@"fn" => Fn,
|
||||
.@"export" => Export,
|
||||
.primitive => Primitive,
|
||||
|
@ -159,6 +161,14 @@ pub const Inst = struct {
|
|||
kw_args: struct {},
|
||||
};
|
||||
|
||||
pub const Return = struct {
|
||||
pub const base_tag = Tag.@"return";
|
||||
base: Inst,
|
||||
|
||||
positionals: struct {},
|
||||
kw_args: struct {},
|
||||
};
|
||||
|
||||
pub const Fn = struct {
|
||||
pub const base_tag = Tag.@"fn";
|
||||
base: Inst,
|
||||
|
@ -417,6 +427,7 @@ pub const Module = struct {
|
|||
.as => return self.writeInstToStreamGeneric(stream, .as, decl, inst_table),
|
||||
.@"asm" => return self.writeInstToStreamGeneric(stream, .@"asm", decl, inst_table),
|
||||
.@"unreachable" => return self.writeInstToStreamGeneric(stream, .@"unreachable", decl, inst_table),
|
||||
.@"return" => return self.writeInstToStreamGeneric(stream, .@"return", decl, inst_table),
|
||||
.@"fn" => return self.writeInstToStreamGeneric(stream, .@"fn", decl, inst_table),
|
||||
.@"export" => return self.writeInstToStreamGeneric(stream, .@"export", decl, inst_table),
|
||||
.primitive => return self.writeInstToStreamGeneric(stream, .primitive, decl, inst_table),
|
||||
|
@ -1000,14 +1011,15 @@ const EmitZIR = struct {
|
|||
|
||||
const fn_type = try self.emitType(src, module_fn.fn_type);
|
||||
|
||||
const arena_instrs = try self.arena.allocator.alloc(*Inst, instructions.items.len);
|
||||
mem.copy(*Inst, arena_instrs, instructions.items);
|
||||
|
||||
const fn_inst = try self.arena.allocator.create(Inst.Fn);
|
||||
fn_inst.* = .{
|
||||
.base = .{ .src = src, .tag = Inst.Fn.base_tag },
|
||||
.positionals = .{
|
||||
.fn_type = fn_type,
|
||||
.body = .{
|
||||
.instructions = instructions.toOwnedSlice(),
|
||||
},
|
||||
.body = .{ .instructions = arena_instrs },
|
||||
},
|
||||
.kw_args = .{},
|
||||
};
|
||||
|
@ -1035,6 +1047,15 @@ const EmitZIR = struct {
|
|||
};
|
||||
break :blk &unreach_inst.base;
|
||||
},
|
||||
.ret => blk: {
|
||||
const ret_inst = try self.arena.allocator.create(Inst.Return);
|
||||
ret_inst.* = .{
|
||||
.base = .{ .src = inst.src, .tag = Inst.Return.base_tag },
|
||||
.positionals = .{},
|
||||
.kw_args = .{},
|
||||
};
|
||||
break :blk &ret_inst.base;
|
||||
},
|
||||
.constant => unreachable, // excluded from function bodies
|
||||
.assembly => blk: {
|
||||
const old_inst = inst.cast(ir.Inst.Assembly).?;
|
||||
|
|
|
@ -53,6 +53,7 @@ pub const Type = extern union {
|
|||
.noreturn => return .NoReturn,
|
||||
|
||||
.fn_naked_noreturn_no_args => return .Fn,
|
||||
.fn_ccc_void_no_args => return .Fn,
|
||||
|
||||
.array, .array_u8_sentinel_0 => return .Array,
|
||||
.single_const_pointer => return .Pointer,
|
||||
|
@ -184,6 +185,7 @@ pub const Type = extern union {
|
|||
|
||||
.const_slice_u8 => return out_stream.writeAll("[]const u8"),
|
||||
.fn_naked_noreturn_no_args => return out_stream.writeAll("fn() callconv(.Naked) noreturn"),
|
||||
.fn_ccc_void_no_args => return out_stream.writeAll("fn() callconv(.C) void"),
|
||||
.single_const_pointer_to_comptime_int => return out_stream.writeAll("*const comptime_int"),
|
||||
|
||||
.array_u8_sentinel_0 => {
|
||||
|
@ -243,6 +245,7 @@ pub const Type = extern union {
|
|||
.comptime_float => return Value.initTag(.comptime_float_type),
|
||||
.noreturn => return Value.initTag(.noreturn_type),
|
||||
.fn_naked_noreturn_no_args => return Value.initTag(.fn_naked_noreturn_no_args_type),
|
||||
.fn_ccc_void_no_args => return Value.initTag(.fn_ccc_void_no_args_type),
|
||||
.single_const_pointer_to_comptime_int => return Value.initTag(.single_const_pointer_to_comptime_int_type),
|
||||
.const_slice_u8 => return Value.initTag(.const_slice_u8_type),
|
||||
else => {
|
||||
|
@ -284,6 +287,7 @@ pub const Type = extern union {
|
|||
.array_u8_sentinel_0,
|
||||
.const_slice_u8,
|
||||
.fn_naked_noreturn_no_args,
|
||||
.fn_ccc_void_no_args,
|
||||
.int_unsigned,
|
||||
.int_signed,
|
||||
=> false,
|
||||
|
@ -326,6 +330,7 @@ pub const Type = extern union {
|
|||
.single_const_pointer,
|
||||
.single_const_pointer_to_comptime_int,
|
||||
.fn_naked_noreturn_no_args,
|
||||
.fn_ccc_void_no_args,
|
||||
.int_unsigned,
|
||||
.int_signed,
|
||||
=> false,
|
||||
|
@ -365,6 +370,7 @@ pub const Type = extern union {
|
|||
.array,
|
||||
.array_u8_sentinel_0,
|
||||
.fn_naked_noreturn_no_args,
|
||||
.fn_ccc_void_no_args,
|
||||
.int_unsigned,
|
||||
.int_signed,
|
||||
=> unreachable,
|
||||
|
@ -405,6 +411,7 @@ pub const Type = extern union {
|
|||
.comptime_float,
|
||||
.noreturn,
|
||||
.fn_naked_noreturn_no_args,
|
||||
.fn_ccc_void_no_args,
|
||||
.int_unsigned,
|
||||
.int_signed,
|
||||
=> unreachable,
|
||||
|
@ -445,6 +452,7 @@ pub const Type = extern union {
|
|||
.comptime_float,
|
||||
.noreturn,
|
||||
.fn_naked_noreturn_no_args,
|
||||
.fn_ccc_void_no_args,
|
||||
.single_const_pointer,
|
||||
.single_const_pointer_to_comptime_int,
|
||||
.const_slice_u8,
|
||||
|
@ -474,6 +482,7 @@ pub const Type = extern union {
|
|||
.comptime_float,
|
||||
.noreturn,
|
||||
.fn_naked_noreturn_no_args,
|
||||
.fn_ccc_void_no_args,
|
||||
.array,
|
||||
.single_const_pointer,
|
||||
.single_const_pointer_to_comptime_int,
|
||||
|
@ -516,6 +525,7 @@ pub const Type = extern union {
|
|||
.comptime_float,
|
||||
.noreturn,
|
||||
.fn_naked_noreturn_no_args,
|
||||
.fn_ccc_void_no_args,
|
||||
.array,
|
||||
.single_const_pointer,
|
||||
.single_const_pointer_to_comptime_int,
|
||||
|
@ -570,6 +580,7 @@ pub const Type = extern union {
|
|||
pub fn fnParamLen(self: Type) usize {
|
||||
return switch (self.tag()) {
|
||||
.fn_naked_noreturn_no_args => 0,
|
||||
.fn_ccc_void_no_args => 0,
|
||||
|
||||
.f16,
|
||||
.f32,
|
||||
|
@ -612,6 +623,7 @@ pub const Type = extern union {
|
|||
pub fn fnParamTypes(self: Type, types: []Type) void {
|
||||
switch (self.tag()) {
|
||||
.fn_naked_noreturn_no_args => return,
|
||||
.fn_ccc_void_no_args => return,
|
||||
|
||||
.f16,
|
||||
.f32,
|
||||
|
@ -653,6 +665,7 @@ pub const Type = extern union {
|
|||
pub fn fnReturnType(self: Type) Type {
|
||||
return switch (self.tag()) {
|
||||
.fn_naked_noreturn_no_args => Type.initTag(.noreturn),
|
||||
.fn_ccc_void_no_args => Type.initTag(.void),
|
||||
|
||||
.f16,
|
||||
.f32,
|
||||
|
@ -694,6 +707,7 @@ pub const Type = extern union {
|
|||
pub fn fnCallingConvention(self: Type) std.builtin.CallingConvention {
|
||||
return switch (self.tag()) {
|
||||
.fn_naked_noreturn_no_args => .Naked,
|
||||
.fn_ccc_void_no_args => .C,
|
||||
|
||||
.f16,
|
||||
.f32,
|
||||
|
@ -763,6 +777,7 @@ pub const Type = extern union {
|
|||
.anyerror,
|
||||
.noreturn,
|
||||
.fn_naked_noreturn_no_args,
|
||||
.fn_ccc_void_no_args,
|
||||
.array,
|
||||
.single_const_pointer,
|
||||
.single_const_pointer_to_comptime_int,
|
||||
|
@ -798,6 +813,7 @@ pub const Type = extern union {
|
|||
.type,
|
||||
.anyerror,
|
||||
.fn_naked_noreturn_no_args,
|
||||
.fn_ccc_void_no_args,
|
||||
.single_const_pointer_to_comptime_int,
|
||||
.array_u8_sentinel_0,
|
||||
.const_slice_u8,
|
||||
|
@ -850,6 +866,7 @@ pub const Type = extern union {
|
|||
.type,
|
||||
.anyerror,
|
||||
.fn_naked_noreturn_no_args,
|
||||
.fn_ccc_void_no_args,
|
||||
.single_const_pointer_to_comptime_int,
|
||||
.array_u8_sentinel_0,
|
||||
.const_slice_u8,
|
||||
|
@ -898,6 +915,7 @@ pub const Type = extern union {
|
|||
comptime_float,
|
||||
noreturn,
|
||||
fn_naked_noreturn_no_args,
|
||||
fn_ccc_void_no_args,
|
||||
single_const_pointer_to_comptime_int,
|
||||
const_slice_u8, // See last_no_payload_tag below.
|
||||
// After this, the tag requires a payload.
|
||||
|
|
|
@ -45,6 +45,7 @@ pub const Value = extern union {
|
|||
comptime_float_type,
|
||||
noreturn_type,
|
||||
fn_naked_noreturn_no_args_type,
|
||||
fn_ccc_void_no_args_type,
|
||||
single_const_pointer_to_comptime_int_type,
|
||||
const_slice_u8_type,
|
||||
|
||||
|
@ -134,6 +135,7 @@ pub const Value = extern union {
|
|||
.comptime_float_type => return out_stream.writeAll("comptime_float"),
|
||||
.noreturn_type => return out_stream.writeAll("noreturn"),
|
||||
.fn_naked_noreturn_no_args_type => return out_stream.writeAll("fn() callconv(.Naked) noreturn"),
|
||||
.fn_ccc_void_no_args_type => return out_stream.writeAll("fn() callconv(.C) void"),
|
||||
.single_const_pointer_to_comptime_int_type => return out_stream.writeAll("*const comptime_int"),
|
||||
.const_slice_u8_type => return out_stream.writeAll("[]const u8"),
|
||||
|
||||
|
@ -202,6 +204,7 @@ pub const Value = extern union {
|
|||
.comptime_float_type => Type.initTag(.@"comptime_float"),
|
||||
.noreturn_type => Type.initTag(.@"noreturn"),
|
||||
.fn_naked_noreturn_no_args_type => Type.initTag(.fn_naked_noreturn_no_args),
|
||||
.fn_ccc_void_no_args_type => Type.initTag(.fn_ccc_void_no_args),
|
||||
.single_const_pointer_to_comptime_int_type => Type.initTag(.single_const_pointer_to_comptime_int),
|
||||
.const_slice_u8_type => Type.initTag(.const_slice_u8),
|
||||
|
||||
|
@ -253,6 +256,7 @@ pub const Value = extern union {
|
|||
.comptime_float_type,
|
||||
.noreturn_type,
|
||||
.fn_naked_noreturn_no_args_type,
|
||||
.fn_ccc_void_no_args_type,
|
||||
.single_const_pointer_to_comptime_int_type,
|
||||
.const_slice_u8_type,
|
||||
.bool_true,
|
||||
|
@ -306,6 +310,7 @@ pub const Value = extern union {
|
|||
.comptime_float_type,
|
||||
.noreturn_type,
|
||||
.fn_naked_noreturn_no_args_type,
|
||||
.fn_ccc_void_no_args_type,
|
||||
.single_const_pointer_to_comptime_int_type,
|
||||
.const_slice_u8_type,
|
||||
.bool_true,
|
||||
|
@ -360,6 +365,7 @@ pub const Value = extern union {
|
|||
.comptime_float_type,
|
||||
.noreturn_type,
|
||||
.fn_naked_noreturn_no_args_type,
|
||||
.fn_ccc_void_no_args_type,
|
||||
.single_const_pointer_to_comptime_int_type,
|
||||
.const_slice_u8_type,
|
||||
.bool_true,
|
||||
|
@ -419,6 +425,7 @@ pub const Value = extern union {
|
|||
.comptime_float_type,
|
||||
.noreturn_type,
|
||||
.fn_naked_noreturn_no_args_type,
|
||||
.fn_ccc_void_no_args_type,
|
||||
.single_const_pointer_to_comptime_int_type,
|
||||
.const_slice_u8_type,
|
||||
.bool_true,
|
||||
|
@ -500,6 +507,7 @@ pub const Value = extern union {
|
|||
.comptime_float_type,
|
||||
.noreturn_type,
|
||||
.fn_naked_noreturn_no_args_type,
|
||||
.fn_ccc_void_no_args_type,
|
||||
.single_const_pointer_to_comptime_int_type,
|
||||
.const_slice_u8_type,
|
||||
.bool_true,
|
||||
|
@ -550,6 +558,7 @@ pub const Value = extern union {
|
|||
.comptime_float_type,
|
||||
.noreturn_type,
|
||||
.fn_naked_noreturn_no_args_type,
|
||||
.fn_ccc_void_no_args_type,
|
||||
.single_const_pointer_to_comptime_int_type,
|
||||
.const_slice_u8_type,
|
||||
.bool_true,
|
||||
|
@ -639,6 +648,7 @@ pub const Value = extern union {
|
|||
.comptime_float_type,
|
||||
.noreturn_type,
|
||||
.fn_naked_noreturn_no_args_type,
|
||||
.fn_ccc_void_no_args_type,
|
||||
.single_const_pointer_to_comptime_int_type,
|
||||
.const_slice_u8_type,
|
||||
.zero,
|
||||
|
@ -691,6 +701,7 @@ pub const Value = extern union {
|
|||
.comptime_float_type,
|
||||
.noreturn_type,
|
||||
.fn_naked_noreturn_no_args_type,
|
||||
.fn_ccc_void_no_args_type,
|
||||
.single_const_pointer_to_comptime_int_type,
|
||||
.const_slice_u8_type,
|
||||
.zero,
|
||||
|
@ -754,6 +765,7 @@ pub const Value = extern union {
|
|||
.comptime_float_type,
|
||||
.noreturn_type,
|
||||
.fn_naked_noreturn_no_args_type,
|
||||
.fn_ccc_void_no_args_type,
|
||||
.single_const_pointer_to_comptime_int_type,
|
||||
.const_slice_u8_type,
|
||||
.zero,
|
||||
|
|
Loading…
Reference in New Issue