ZIR: implement return instruction

master
Andrew Kelley 2020-04-28 21:40:51 -04:00
parent 6b0f7de247
commit 28729efe29
5 changed files with 78 additions and 5 deletions

View File

@ -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);
}

View File

@ -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);

View File

@ -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).?;

View File

@ -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.

View File

@ -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,