| author | |
| committer | |
| log | b1a86040dd530fd5632b22359eb7534dc2e3f4c9 |
| tree | dcf3a68e060acd29eeb7454ff1c84761af1ade1a |
| parent | 993e6545546b499e8052a0020cc10e399c235c11 |
2 files changed, 196 insertions(+), 2 deletions(-)
src-self-hosted/ir/text.zig+39-2| ... | ... | @@ -880,7 +880,20 @@ const EmitZIR = struct { |
| 880 | 880 | break :blk &unreach_inst.base; |
| 881 | 881 | }, |
| 882 | 882 | .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 | }, | |
| 884 | 897 | .ptrtoint => blk: { |
| 885 | 898 | const old_inst = inst.cast(ir.Inst.PtrToInt).?; |
| 886 | 899 | const new_inst = try self.arena.allocator.create(Inst.PtrToInt); |
| ... | ... | @@ -918,7 +931,7 @@ const EmitZIR = struct { |
| 918 | 931 | } |
| 919 | 932 | } |
| 920 | 933 | |
| 921 | pub fn emitType(self: *EmitZIR, src: usize, ty: Type) !*Inst { | |
| 934 | pub fn emitType(self: *EmitZIR, src: usize, ty: Type) Allocator.Error!*Inst { | |
| 922 | 935 | switch (ty.tag()) { |
| 923 | 936 | .isize => return self.emitPrimitiveType(src, .isize), |
| 924 | 937 | .usize => return self.emitPrimitiveType(src, .usize), |
| ... | ... | @@ -944,6 +957,30 @@ const EmitZIR = struct { |
| 944 | 957 | .Type => return self.emitPrimitiveType(src, .type), |
| 945 | 958 | .ComptimeInt => return self.emitPrimitiveType(src, .comptime_int), |
| 946 | 959 | .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 | }, | |
| 947 | 984 | else => std.debug.panic("TODO implement emitType for {}", .{ty}), |
| 948 | 985 | }, |
| 949 | 986 | } |
src-self-hosted/type.zig+157| ... | ... | @@ -422,6 +422,163 @@ pub const Type = extern union { |
| 422 | 422 | }; |
| 423 | 423 | } |
| 424 | 424 | |
| 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 | ||
| 425 | 582 | /// This enum does not directly correspond to `std.builtin.TypeId` because |
| 426 | 583 | /// it has extra enum tags in it, as a way of using less memory. For example, |
| 427 | 584 | /// even though Zig recognizes `*align(10) i32` and `*i32` both as Pointer types |