Commit b1a86040dd
src-self-hosted/ir/text.zig
@@ -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}),
},
}
src-self-hosted/type.zig
@@ -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