authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-04-22 00:26:37-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-04-22 00:26:37-04:00
logb1a86040dd530fd5632b22359eb7534dc2e3f4c9
treedcf3a68e060acd29eeb7454ff1c84761af1ade1a
parent993e6545546b499e8052a0020cc10e399c235c11

ir: emit zir for fntype


2 files changed, 196 insertions(+), 2 deletions(-)

src-self-hosted/ir/text.zig+39-2
......@@ -880,7 +880,20 @@ const EmitZIR = struct {
880880 break :blk &unreach_inst.base;
881881 },
882882 .constant => unreachable, // excluded from function bodies
883 .assembly => @panic("TODO emit zir asm instruction"),
883 .assembly => blk: {
884 const old_inst = inst.cast(ir.Inst.Assembly).?;
885 const new_inst = try self.arena.allocator.create(Inst.Asm);
886 new_inst.* = .{
887 .base = .{ .src = inst.src, .tag = Inst.Asm.base_tag },
888 .positionals = .{
889 .asm_source = try self.emitStringLiteral(inst.src, old_inst.args.asm_source),
890 .return_type = try self.emitType(inst.src, inst.ty),
891 },
892 // TODO emit more kw_args
893 .kw_args = .{},
894 };
895 break :blk &new_inst.base;
896 },
884897 .ptrtoint => blk: {
885898 const old_inst = inst.cast(ir.Inst.PtrToInt).?;
886899 const new_inst = try self.arena.allocator.create(Inst.PtrToInt);
......@@ -918,7 +931,7 @@ const EmitZIR = struct {
918931 }
919932 }
920933
921 pub fn emitType(self: *EmitZIR, src: usize, ty: Type) !*Inst {
934 pub fn emitType(self: *EmitZIR, src: usize, ty: Type) Allocator.Error!*Inst {
922935 switch (ty.tag()) {
923936 .isize => return self.emitPrimitiveType(src, .isize),
924937 .usize => return self.emitPrimitiveType(src, .usize),
......@@ -944,6 +957,30 @@ const EmitZIR = struct {
944957 .Type => return self.emitPrimitiveType(src, .type),
945958 .ComptimeInt => return self.emitPrimitiveType(src, .comptime_int),
946959 .ComptimeFloat => return self.emitPrimitiveType(src, .comptime_float),
960 .Fn => {
961 const param_types = try self.allocator.alloc(Type, ty.fnParamLen());
962 defer self.allocator.free(param_types);
963
964 ty.fnParamTypes(param_types);
965 const emitted_params = try self.arena.allocator.alloc(*Inst, param_types.len);
966 for (param_types) |param_type, i| {
967 emitted_params[i] = try self.emitType(src, param_type);
968 }
969
970 const fntype_inst = try self.arena.allocator.create(Inst.FnType);
971 fntype_inst.* = .{
972 .base = .{ .src = src, .tag = Inst.FnType.base_tag },
973 .positionals = .{
974 .param_types = emitted_params,
975 .return_type = try self.emitType(src, ty.fnReturnType()),
976 },
977 .kw_args = .{
978 .cc = ty.fnCallingConvention(),
979 },
980 };
981 try self.decls.append(&fntype_inst.base);
982 return &fntype_inst.base;
983 },
947984 else => std.debug.panic("TODO implement emitType for {}", .{ty}),
948985 },
949986 }
src-self-hosted/type.zig+157
......@@ -422,6 +422,163 @@ pub const Type = extern union {
422422 };
423423 }
424424
425 /// Asserts the type is a function.
426 pub fn fnParamLen(self: Type) usize {
427 return switch (self.tag()) {
428 .fn_naked_noreturn_no_args => 0,
429
430 .f16,
431 .f32,
432 .f64,
433 .f128,
434 .c_longdouble,
435 .c_void,
436 .bool,
437 .void,
438 .type,
439 .anyerror,
440 .comptime_int,
441 .comptime_float,
442 .noreturn,
443 .array,
444 .single_const_pointer,
445 .single_const_pointer_to_comptime_int,
446 .array_u8_sentinel_0,
447 .const_slice_u8,
448 .u8,
449 .i8,
450 .usize,
451 .isize,
452 .c_short,
453 .c_ushort,
454 .c_int,
455 .c_uint,
456 .c_long,
457 .c_ulong,
458 .c_longlong,
459 .c_ulonglong,
460 => unreachable,
461 };
462 }
463
464 /// Asserts the type is a function. The length of the slice must be at least the length
465 /// given by `fnParamLen`.
466 pub fn fnParamTypes(self: Type, types: []Type) void {
467 switch (self.tag()) {
468 .fn_naked_noreturn_no_args => return,
469
470 .f16,
471 .f32,
472 .f64,
473 .f128,
474 .c_longdouble,
475 .c_void,
476 .bool,
477 .void,
478 .type,
479 .anyerror,
480 .comptime_int,
481 .comptime_float,
482 .noreturn,
483 .array,
484 .single_const_pointer,
485 .single_const_pointer_to_comptime_int,
486 .array_u8_sentinel_0,
487 .const_slice_u8,
488 .u8,
489 .i8,
490 .usize,
491 .isize,
492 .c_short,
493 .c_ushort,
494 .c_int,
495 .c_uint,
496 .c_long,
497 .c_ulong,
498 .c_longlong,
499 .c_ulonglong,
500 => unreachable,
501 }
502 }
503
504 /// Asserts the type is a function.
505 pub fn fnReturnType(self: Type) Type {
506 return switch (self.tag()) {
507 .fn_naked_noreturn_no_args => Type.initTag(.noreturn),
508
509 .f16,
510 .f32,
511 .f64,
512 .f128,
513 .c_longdouble,
514 .c_void,
515 .bool,
516 .void,
517 .type,
518 .anyerror,
519 .comptime_int,
520 .comptime_float,
521 .noreturn,
522 .array,
523 .single_const_pointer,
524 .single_const_pointer_to_comptime_int,
525 .array_u8_sentinel_0,
526 .const_slice_u8,
527 .u8,
528 .i8,
529 .usize,
530 .isize,
531 .c_short,
532 .c_ushort,
533 .c_int,
534 .c_uint,
535 .c_long,
536 .c_ulong,
537 .c_longlong,
538 .c_ulonglong,
539 => unreachable,
540 };
541 }
542
543 /// Asserts the type is a function.
544 pub fn fnCallingConvention(self: Type) std.builtin.CallingConvention {
545 return switch (self.tag()) {
546 .fn_naked_noreturn_no_args => .Naked,
547
548 .f16,
549 .f32,
550 .f64,
551 .f128,
552 .c_longdouble,
553 .c_void,
554 .bool,
555 .void,
556 .type,
557 .anyerror,
558 .comptime_int,
559 .comptime_float,
560 .noreturn,
561 .array,
562 .single_const_pointer,
563 .single_const_pointer_to_comptime_int,
564 .array_u8_sentinel_0,
565 .const_slice_u8,
566 .u8,
567 .i8,
568 .usize,
569 .isize,
570 .c_short,
571 .c_ushort,
572 .c_int,
573 .c_uint,
574 .c_long,
575 .c_ulong,
576 .c_longlong,
577 .c_ulonglong,
578 => unreachable,
579 };
580 }
581
425582 /// This enum does not directly correspond to `std.builtin.TypeId` because
426583 /// it has extra enum tags in it, as a way of using less memory. For example,
427584 /// even though Zig recognizes `*align(10) i32` and `*i32` both as Pointer types