ir: emit zir for fntype

This commit is contained in:
Andrew Kelley 2020-04-22 00:26:37 -04:00
parent 993e654554
commit b1a86040dd
2 changed files with 196 additions and 2 deletions

View File

@ -880,7 +880,20 @@ const EmitZIR = struct {
break :blk &unreach_inst.base;
},
.constant => unreachable, // excluded from function bodies
.assembly => @panic("TODO emit zir asm instruction"),
.assembly => blk: {
const old_inst = inst.cast(ir.Inst.Assembly).?;
const new_inst = try self.arena.allocator.create(Inst.Asm);
new_inst.* = .{
.base = .{ .src = inst.src, .tag = Inst.Asm.base_tag },
.positionals = .{
.asm_source = try self.emitStringLiteral(inst.src, old_inst.args.asm_source),
.return_type = try self.emitType(inst.src, inst.ty),
},
// TODO emit more kw_args
.kw_args = .{},
};
break :blk &new_inst.base;
},
.ptrtoint => blk: {
const old_inst = inst.cast(ir.Inst.PtrToInt).?;
const new_inst = try self.arena.allocator.create(Inst.PtrToInt);
@ -918,7 +931,7 @@ const EmitZIR = struct {
}
}
pub fn emitType(self: *EmitZIR, src: usize, ty: Type) !*Inst {
pub fn emitType(self: *EmitZIR, src: usize, ty: Type) Allocator.Error!*Inst {
switch (ty.tag()) {
.isize => return self.emitPrimitiveType(src, .isize),
.usize => return self.emitPrimitiveType(src, .usize),
@ -944,6 +957,30 @@ const EmitZIR = struct {
.Type => return self.emitPrimitiveType(src, .type),
.ComptimeInt => return self.emitPrimitiveType(src, .comptime_int),
.ComptimeFloat => return self.emitPrimitiveType(src, .comptime_float),
.Fn => {
const param_types = try self.allocator.alloc(Type, ty.fnParamLen());
defer self.allocator.free(param_types);
ty.fnParamTypes(param_types);
const emitted_params = try self.arena.allocator.alloc(*Inst, param_types.len);
for (param_types) |param_type, i| {
emitted_params[i] = try self.emitType(src, param_type);
}
const fntype_inst = try self.arena.allocator.create(Inst.FnType);
fntype_inst.* = .{
.base = .{ .src = src, .tag = Inst.FnType.base_tag },
.positionals = .{
.param_types = emitted_params,
.return_type = try self.emitType(src, ty.fnReturnType()),
},
.kw_args = .{
.cc = ty.fnCallingConvention(),
},
};
try self.decls.append(&fntype_inst.base);
return &fntype_inst.base;
},
else => std.debug.panic("TODO implement emitType for {}", .{ty}),
},
}

View File

@ -422,6 +422,163 @@ pub const Type = extern union {
};
}
/// Asserts the type is a function.
pub fn fnParamLen(self: Type) usize {
return switch (self.tag()) {
.fn_naked_noreturn_no_args => 0,
.f16,
.f32,
.f64,
.f128,
.c_longdouble,
.c_void,
.bool,
.void,
.type,
.anyerror,
.comptime_int,
.comptime_float,
.noreturn,
.array,
.single_const_pointer,
.single_const_pointer_to_comptime_int,
.array_u8_sentinel_0,
.const_slice_u8,
.u8,
.i8,
.usize,
.isize,
.c_short,
.c_ushort,
.c_int,
.c_uint,
.c_long,
.c_ulong,
.c_longlong,
.c_ulonglong,
=> unreachable,
};
}
/// Asserts the type is a function. The length of the slice must be at least the length
/// given by `fnParamLen`.
pub fn fnParamTypes(self: Type, types: []Type) void {
switch (self.tag()) {
.fn_naked_noreturn_no_args => return,
.f16,
.f32,
.f64,
.f128,
.c_longdouble,
.c_void,
.bool,
.void,
.type,
.anyerror,
.comptime_int,
.comptime_float,
.noreturn,
.array,
.single_const_pointer,
.single_const_pointer_to_comptime_int,
.array_u8_sentinel_0,
.const_slice_u8,
.u8,
.i8,
.usize,
.isize,
.c_short,
.c_ushort,
.c_int,
.c_uint,
.c_long,
.c_ulong,
.c_longlong,
.c_ulonglong,
=> unreachable,
}
}
/// Asserts the type is a function.
pub fn fnReturnType(self: Type) Type {
return switch (self.tag()) {
.fn_naked_noreturn_no_args => Type.initTag(.noreturn),
.f16,
.f32,
.f64,
.f128,
.c_longdouble,
.c_void,
.bool,
.void,
.type,
.anyerror,
.comptime_int,
.comptime_float,
.noreturn,
.array,
.single_const_pointer,
.single_const_pointer_to_comptime_int,
.array_u8_sentinel_0,
.const_slice_u8,
.u8,
.i8,
.usize,
.isize,
.c_short,
.c_ushort,
.c_int,
.c_uint,
.c_long,
.c_ulong,
.c_longlong,
.c_ulonglong,
=> unreachable,
};
}
/// Asserts the type is a function.
pub fn fnCallingConvention(self: Type) std.builtin.CallingConvention {
return switch (self.tag()) {
.fn_naked_noreturn_no_args => .Naked,
.f16,
.f32,
.f64,
.f128,
.c_longdouble,
.c_void,
.bool,
.void,
.type,
.anyerror,
.comptime_int,
.comptime_float,
.noreturn,
.array,
.single_const_pointer,
.single_const_pointer_to_comptime_int,
.array_u8_sentinel_0,
.const_slice_u8,
.u8,
.i8,
.usize,
.isize,
.c_short,
.c_ushort,
.c_int,
.c_uint,
.c_long,
.c_ulong,
.c_longlong,
.c_ulonglong,
=> unreachable,
};
}
/// This enum does not directly correspond to `std.builtin.TypeId` because
/// it has extra enum tags in it, as a way of using less memory. For example,
/// even though Zig recognizes `*align(10) i32` and `*i32` both as Pointer types