| ... | ... | @@ -179,6 +179,14 @@ pub const DeclGen = struct { |
| 179 | 179 | return error.AnalysisFail; |
| 180 | 180 | } |
| 181 | 181 | |
| 182 | fn getTypedefName(dg: *DeclGen, t: Type) ?[]const u8 { |
| 183 | if (dg.typedefs.get(t)) |some| { |
| 184 | return some.name; |
| 185 | } else { |
| 186 | return null; |
| 187 | } |
| 188 | } |
| 189 | |
| 182 | 190 | fn renderDeclValue( |
| 183 | 191 | dg: *DeclGen, |
| 184 | 192 | writer: anytype, |
| ... | ... | @@ -200,14 +208,20 @@ pub const DeclGen = struct { |
| 200 | 208 | return; |
| 201 | 209 | } |
| 202 | 210 | |
| 203 | | // Determine if we must pointer cast. |
| 204 | 211 | assert(decl.has_tv); |
| 205 | | if (ty.eql(decl.ty)) { |
| 206 | | try writer.writeByte('&'); |
| 207 | | } else { |
| 208 | | try writer.writeAll("("); |
| 209 | | try dg.renderType(writer, ty); |
| 210 | | try writer.writeAll(")&"); |
| 212 | // We shouldn't cast C function pointers as this is UB (when you call |
| 213 | // them). The analysis until now should ensure that the C function |
| 214 | // pointers are compatible. If they are not, then there is a bug |
| 215 | // somewhere and we should let the C compiler tell us about it. |
| 216 | if (ty.castPtrToFn() == null) { |
| 217 | // Determine if we must pointer cast. |
| 218 | if (ty.eql(decl.ty)) { |
| 219 | try writer.writeByte('&'); |
| 220 | } else { |
| 221 | try writer.writeAll("("); |
| 222 | try dg.renderType(writer, ty); |
| 223 | try writer.writeAll(")&"); |
| 224 | } |
| 211 | 225 | } |
| 212 | 226 | try dg.renderDeclName(decl, writer); |
| 213 | 227 | } |
| ... | ... | @@ -514,7 +528,190 @@ pub const DeclGen = struct { |
| 514 | 528 | try w.writeByte(')'); |
| 515 | 529 | } |
| 516 | 530 | |
| 531 | fn renderPtrToFnTypedef(dg: *DeclGen, t: Type, fn_ty: Type) error{ OutOfMemory, AnalysisFail }![]const u8 { |
| 532 | var buffer = std.ArrayList(u8).init(dg.typedefs.allocator); |
| 533 | defer buffer.deinit(); |
| 534 | const bw = buffer.writer(); |
| 535 | |
| 536 | const fn_info = fn_ty.fnInfo(); |
| 537 | |
| 538 | try bw.writeAll("typedef "); |
| 539 | try dg.renderType(bw, fn_info.return_type); |
| 540 | try bw.writeAll(" (*"); |
| 541 | |
| 542 | const name_start = buffer.items.len; |
| 543 | // TODO: typeToCIdentifier truncates to 128 bytes, we probably don't want to do this |
| 544 | try bw.print("zig_F_{s})(", .{typeToCIdentifier(t)}); |
| 545 | const name_end = buffer.items.len - 2; |
| 546 | |
| 547 | const param_len = fn_info.param_types.len; |
| 548 | const is_var_args = fn_info.is_var_args; |
| 549 | if (param_len == 0 and !is_var_args) |
| 550 | try bw.writeAll("void") |
| 551 | else { |
| 552 | var index: usize = 0; |
| 553 | while (index < param_len) : (index += 1) { |
| 554 | if (index > 0) { |
| 555 | try bw.writeAll(", "); |
| 556 | } |
| 557 | try dg.renderType(bw, fn_info.param_types[index]); |
| 558 | } |
| 559 | } |
| 560 | if (is_var_args) { |
| 561 | if (param_len != 0) try bw.writeAll(", "); |
| 562 | try bw.writeAll("..."); |
| 563 | } |
| 564 | try bw.writeAll(");\n"); |
| 565 | |
| 566 | const rendered = buffer.toOwnedSlice(); |
| 567 | errdefer dg.typedefs.allocator.free(rendered); |
| 568 | const name = rendered[name_start..name_end]; |
| 569 | |
| 570 | try dg.typedefs.ensureUnusedCapacity(1); |
| 571 | dg.typedefs.putAssumeCapacityNoClobber( |
| 572 | try t.copy(dg.typedefs_arena), |
| 573 | .{ .name = name, .rendered = rendered }, |
| 574 | ); |
| 575 | |
| 576 | return name; |
| 577 | } |
| 578 | |
| 579 | fn renderSliceTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 { |
| 580 | var buffer = std.ArrayList(u8).init(dg.typedefs.allocator); |
| 581 | defer buffer.deinit(); |
| 582 | const bw = buffer.writer(); |
| 583 | |
| 584 | try bw.writeAll("typedef struct { "); |
| 585 | const elem_type = t.elemType(); |
| 586 | try dg.renderType(bw, elem_type); |
| 587 | if (t.isConstPtr()) { |
| 588 | try bw.writeAll(" const"); |
| 589 | } |
| 590 | if (t.isVolatilePtr()) { |
| 591 | try bw.writeAll(" volatile"); |
| 592 | } |
| 593 | try bw.writeAll(" *"); |
| 594 | try bw.writeAll("ptr; size_t len; } "); |
| 595 | const name_index = buffer.items.len; |
| 596 | if (t.isConstPtr()) { |
| 597 | try bw.print("zig_L_{s};\n", .{typeToCIdentifier(elem_type)}); |
| 598 | } else { |
| 599 | try bw.print("zig_M_{s};\n", .{typeToCIdentifier(elem_type)}); |
| 600 | } |
| 601 | |
| 602 | const rendered = buffer.toOwnedSlice(); |
| 603 | errdefer dg.typedefs.allocator.free(rendered); |
| 604 | const name = rendered[name_index .. rendered.len - 2]; |
| 605 | |
| 606 | try dg.typedefs.ensureUnusedCapacity(1); |
| 607 | dg.typedefs.putAssumeCapacityNoClobber( |
| 608 | try t.copy(dg.typedefs_arena), |
| 609 | .{ .name = name, .rendered = rendered }, |
| 610 | ); |
| 611 | |
| 612 | return name; |
| 613 | } |
| 614 | |
| 615 | fn renderStructTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 { |
| 616 | const struct_obj = t.castTag(.@"struct").?.data; // Handle 0 bit types elsewhere. |
| 617 | const fqn = try struct_obj.getFullyQualifiedName(dg.typedefs.allocator); |
| 618 | defer dg.typedefs.allocator.free(fqn); |
| 619 | |
| 620 | var buffer = std.ArrayList(u8).init(dg.typedefs.allocator); |
| 621 | defer buffer.deinit(); |
| 622 | |
| 623 | try buffer.appendSlice("typedef struct {\n"); |
| 624 | { |
| 625 | var it = struct_obj.fields.iterator(); |
| 626 | while (it.next()) |entry| { |
| 627 | const field_ty = entry.value_ptr.ty; |
| 628 | const name: CValue = .{ .bytes = entry.key_ptr.* }; |
| 629 | try buffer.append(' '); |
| 630 | try dg.renderTypeAndName(buffer.writer(), field_ty, name, .Mut); |
| 631 | try buffer.appendSlice(";\n"); |
| 632 | } |
| 633 | } |
| 634 | try buffer.appendSlice("} "); |
| 635 | |
| 636 | const name_start = buffer.items.len; |
| 637 | try buffer.writer().print("zig_S_{s};\n", .{fmtIdent(fqn)}); |
| 638 | |
| 639 | const rendered = buffer.toOwnedSlice(); |
| 640 | errdefer dg.typedefs.allocator.free(rendered); |
| 641 | const name = rendered[name_start .. rendered.len - 2]; |
| 642 | |
| 643 | try dg.typedefs.ensureUnusedCapacity(1); |
| 644 | dg.typedefs.putAssumeCapacityNoClobber( |
| 645 | try t.copy(dg.typedefs_arena), |
| 646 | .{ .name = name, .rendered = rendered }, |
| 647 | ); |
| 648 | |
| 649 | return name; |
| 650 | } |
| 651 | |
| 652 | fn renderErrorUnionTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 { |
| 653 | const child_type = t.errorUnionPayload(); |
| 654 | const err_set_type = t.errorUnionSet(); |
| 655 | |
| 656 | var buffer = std.ArrayList(u8).init(dg.typedefs.allocator); |
| 657 | defer buffer.deinit(); |
| 658 | const bw = buffer.writer(); |
| 659 | |
| 660 | try bw.writeAll("typedef struct { "); |
| 661 | try dg.renderType(bw, child_type); |
| 662 | try bw.writeAll(" payload; uint16_t error; } "); |
| 663 | const name_index = buffer.items.len; |
| 664 | if (err_set_type.castTag(.error_set_inferred)) |inf_err_set_payload| { |
| 665 | const func = inf_err_set_payload.data.func; |
| 666 | try bw.writeAll("zig_E_"); |
| 667 | try dg.renderDeclName(func.owner_decl, bw); |
| 668 | try bw.writeAll(";\n"); |
| 669 | } else { |
| 670 | try bw.print("zig_E_{s}_{s};\n", .{ |
| 671 | typeToCIdentifier(err_set_type), typeToCIdentifier(child_type), |
| 672 | }); |
| 673 | } |
| 674 | |
| 675 | const rendered = buffer.toOwnedSlice(); |
| 676 | errdefer dg.typedefs.allocator.free(rendered); |
| 677 | const name = rendered[name_index .. rendered.len - 2]; |
| 678 | |
| 679 | try dg.typedefs.ensureUnusedCapacity(1); |
| 680 | dg.typedefs.putAssumeCapacityNoClobber( |
| 681 | try t.copy(dg.typedefs_arena), |
| 682 | .{ .name = name, .rendered = rendered }, |
| 683 | ); |
| 684 | |
| 685 | return name; |
| 686 | } |
| 687 | |
| 688 | fn renderOptionalTypedef(dg: *DeclGen, t: Type, child_type: Type) error{ OutOfMemory, AnalysisFail }![]const u8 { |
| 689 | var buffer = std.ArrayList(u8).init(dg.typedefs.allocator); |
| 690 | defer buffer.deinit(); |
| 691 | const bw = buffer.writer(); |
| 692 | |
| 693 | try bw.writeAll("typedef struct { "); |
| 694 | try dg.renderType(bw, child_type); |
| 695 | try bw.writeAll(" payload; bool is_null; } "); |
| 696 | const name_index = buffer.items.len; |
| 697 | try bw.print("zig_Q_{s};\n", .{typeToCIdentifier(child_type)}); |
| 698 | |
| 699 | const rendered = buffer.toOwnedSlice(); |
| 700 | errdefer dg.typedefs.allocator.free(rendered); |
| 701 | const name = rendered[name_index .. rendered.len - 2]; |
| 702 | |
| 703 | try dg.typedefs.ensureUnusedCapacity(1); |
| 704 | dg.typedefs.putAssumeCapacityNoClobber( |
| 705 | try t.copy(dg.typedefs_arena), |
| 706 | .{ .name = name, .rendered = rendered }, |
| 707 | ); |
| 708 | |
| 709 | return name; |
| 710 | } |
| 711 | |
| 517 | 712 | fn renderType(dg: *DeclGen, w: anytype, t: Type) error{ OutOfMemory, AnalysisFail }!void { |
| 713 | const target = dg.module.getTarget(); |
| 714 | |
| 518 | 715 | switch (t.zigTypeTag()) { |
| 519 | 716 | .NoReturn => { |
| 520 | 717 | try w.writeAll("zig_noreturn void"); |
| ... | ... | @@ -542,7 +739,7 @@ pub const DeclGen = struct { |
| 542 | 739 | .c_longlong => try w.writeAll("long long"), |
| 543 | 740 | .c_ulonglong => try w.writeAll("unsigned long long"), |
| 544 | 741 | .int_signed, .int_unsigned => { |
| 545 | | const info = t.intInfo(dg.module.getTarget()); |
| 742 | const info = t.intInfo(target); |
| 546 | 743 | const sign_prefix = switch (info.signedness) { |
| 547 | 744 | .signed => "", |
| 548 | 745 | .unsigned => "u", |
| ... | ... | @@ -554,7 +751,6 @@ pub const DeclGen = struct { |
| 554 | 751 | else => unreachable, |
| 555 | 752 | } |
| 556 | 753 | }, |
| 557 | | |
| 558 | 754 | .Float => { |
| 559 | 755 | switch (t.tag()) { |
| 560 | 756 | .f32 => try w.writeAll("float"), |
| ... | ... | @@ -565,196 +761,71 @@ pub const DeclGen = struct { |
| 565 | 761 | else => unreachable, |
| 566 | 762 | } |
| 567 | 763 | }, |
| 568 | | |
| 569 | 764 | .Pointer => { |
| 570 | 765 | if (t.isSlice()) { |
| 571 | | if (dg.typedefs.get(t)) |some| { |
| 572 | | return w.writeAll(some.name); |
| 573 | | } |
| 766 | const name = dg.getTypedefName(t) orelse |
| 767 | try dg.renderSliceTypedef(t); |
| 574 | 768 | |
| 575 | | var buffer = std.ArrayList(u8).init(dg.typedefs.allocator); |
| 576 | | defer buffer.deinit(); |
| 577 | | const bw = buffer.writer(); |
| 578 | | |
| 579 | | try bw.writeAll("typedef struct { "); |
| 580 | | const elem_type = t.elemType(); |
| 581 | | try dg.renderType(bw, elem_type); |
| 582 | | try bw.writeAll(" *"); |
| 583 | | // We skip the const qualifier because C's type system |
| 584 | | // would not allow a local mutable variable which is this slice type |
| 585 | | // to be overwritten with a new slice type. |
| 586 | | if (t.isVolatilePtr()) { |
| 587 | | try bw.writeAll("volatile "); |
| 588 | | } |
| 589 | | try bw.writeAll("ptr; size_t len; } "); |
| 590 | | const name_index = buffer.items.len; |
| 591 | | try bw.print("zig_L_{s};\n", .{typeToCIdentifier(elem_type)}); |
| 592 | | |
| 593 | | const rendered = buffer.toOwnedSlice(); |
| 594 | | errdefer dg.typedefs.allocator.free(rendered); |
| 595 | | const name = rendered[name_index .. rendered.len - 2]; |
| 596 | | |
| 597 | | try dg.typedefs.ensureUnusedCapacity(1); |
| 598 | | try w.writeAll(name); |
| 599 | | dg.typedefs.putAssumeCapacityNoClobber( |
| 600 | | try t.copy(dg.typedefs_arena), |
| 601 | | .{ .name = name, .rendered = rendered }, |
| 602 | | ); |
| 603 | | return; |
| 769 | return w.writeAll(name); |
| 604 | 770 | } |
| 771 | |
| 605 | 772 | if (t.castPtrToFn()) |fn_ty| { |
| 606 | | const fn_info = fn_ty.fnInfo(); |
| 607 | | try dg.renderType(w, fn_info.return_type); |
| 608 | | try w.writeAll(" (*)("); |
| 609 | | const param_len = fn_info.param_types.len; |
| 610 | | const is_var_args = fn_info.is_var_args; |
| 611 | | if (param_len == 0 and !is_var_args) |
| 612 | | try w.writeAll("void") |
| 613 | | else { |
| 614 | | var index: usize = 0; |
| 615 | | while (index < param_len) : (index += 1) { |
| 616 | | if (index > 0) { |
| 617 | | try w.writeAll(", "); |
| 618 | | } |
| 619 | | try dg.renderType(w, fn_info.param_types[index]); |
| 620 | | } |
| 621 | | } |
| 622 | | if (is_var_args) { |
| 623 | | if (param_len != 0) try w.writeAll(", "); |
| 624 | | try w.writeAll("..."); |
| 625 | | } |
| 626 | | try w.writeByte(')'); |
| 627 | | return; |
| 773 | const name = dg.getTypedefName(t) orelse |
| 774 | try dg.renderPtrToFnTypedef(t, fn_ty); |
| 775 | |
| 776 | return w.writeAll(name); |
| 628 | 777 | } |
| 629 | 778 | |
| 630 | 779 | try dg.renderType(w, t.elemType()); |
| 631 | | try w.writeAll(" *"); |
| 632 | 780 | if (t.isConstPtr()) { |
| 633 | | try w.writeAll("const "); |
| 781 | try w.writeAll(" const"); |
| 634 | 782 | } |
| 635 | 783 | if (t.isVolatilePtr()) { |
| 636 | | try w.writeAll("volatile "); |
| 784 | try w.writeAll(" volatile"); |
| 637 | 785 | } |
| 786 | return w.writeAll(" *"); |
| 638 | 787 | }, |
| 639 | 788 | .Array => { |
| 789 | // We are referencing the array so it will decay to a C pointer. |
| 640 | 790 | try dg.renderType(w, t.elemType()); |
| 641 | | try w.writeAll(" *"); |
| 791 | return w.writeAll(" *"); |
| 642 | 792 | }, |
| 643 | 793 | .Optional => { |
| 644 | 794 | var opt_buf: Type.Payload.ElemType = undefined; |
| 645 | 795 | const child_type = t.optionalChild(&opt_buf); |
| 646 | | const target = dg.module.getTarget(); |
| 796 | |
| 647 | 797 | if (t.isPtrLikeOptional()) { |
| 648 | 798 | return dg.renderType(w, child_type); |
| 649 | | } else if (dg.typedefs.get(t)) |some| { |
| 650 | | return w.writeAll(some.name); |
| 651 | | } else if (child_type.abiSize(target) == 0) { |
| 799 | } |
| 800 | |
| 801 | if (child_type.abiSize(target) == 0) { |
| 652 | 802 | return w.writeAll("bool"); |
| 653 | 803 | } |
| 654 | 804 | |
| 655 | | var buffer = std.ArrayList(u8).init(dg.typedefs.allocator); |
| 656 | | defer buffer.deinit(); |
| 657 | | const bw = buffer.writer(); |
| 658 | | |
| 659 | | try bw.writeAll("typedef struct { "); |
| 660 | | try dg.renderType(bw, child_type); |
| 661 | | try bw.writeAll(" payload; bool is_null; } "); |
| 662 | | const name_index = buffer.items.len; |
| 663 | | try bw.print("zig_Q_{s};\n", .{typeToCIdentifier(child_type)}); |
| 664 | | |
| 665 | | const rendered = buffer.toOwnedSlice(); |
| 666 | | errdefer dg.typedefs.allocator.free(rendered); |
| 667 | | const name = rendered[name_index .. rendered.len - 2]; |
| 668 | | |
| 669 | | try dg.typedefs.ensureUnusedCapacity(1); |
| 670 | | try w.writeAll(name); |
| 671 | | dg.typedefs.putAssumeCapacityNoClobber( |
| 672 | | try t.copy(dg.typedefs_arena), |
| 673 | | .{ .name = name, .rendered = rendered }, |
| 674 | | ); |
| 805 | const name = dg.getTypedefName(t) orelse |
| 806 | try dg.renderOptionalTypedef(t, child_type); |
| 807 | |
| 808 | return w.writeAll(name); |
| 675 | 809 | }, |
| 676 | 810 | .ErrorSet => { |
| 677 | 811 | comptime std.debug.assert(Type.initTag(.anyerror).abiSize(builtin.target) == 2); |
| 678 | | try w.writeAll("uint16_t"); |
| 812 | return w.writeAll("uint16_t"); |
| 679 | 813 | }, |
| 680 | 814 | .ErrorUnion => { |
| 681 | | if (dg.typedefs.get(t)) |some| { |
| 682 | | return w.writeAll(some.name); |
| 683 | | } |
| 684 | | const child_type = t.errorUnionPayload(); |
| 685 | | const err_set_type = t.errorUnionSet(); |
| 686 | | |
| 687 | | if (!child_type.hasCodeGenBits()) { |
| 688 | | return dg.renderType(w, err_set_type); |
| 689 | | } |
| 690 | | |
| 691 | | var buffer = std.ArrayList(u8).init(dg.typedefs.allocator); |
| 692 | | defer buffer.deinit(); |
| 693 | | const bw = buffer.writer(); |
| 694 | | |
| 695 | | try bw.writeAll("typedef struct { "); |
| 696 | | try dg.renderType(bw, child_type); |
| 697 | | try bw.writeAll(" payload; uint16_t error; } "); |
| 698 | | const name_index = buffer.items.len; |
| 699 | | if (err_set_type.castTag(.error_set_inferred)) |inf_err_set_payload| { |
| 700 | | const func = inf_err_set_payload.data.func; |
| 701 | | try bw.writeAll("zig_E_"); |
| 702 | | try dg.renderDeclName(func.owner_decl, bw); |
| 703 | | try bw.writeAll(";\n"); |
| 704 | | } else { |
| 705 | | try bw.print("zig_E_{s}_{s};\n", .{ |
| 706 | | typeToCIdentifier(err_set_type), typeToCIdentifier(child_type), |
| 707 | | }); |
| 815 | if (t.errorUnionPayload().abiSize(target) == 0) { |
| 816 | return dg.renderType(w, t.errorUnionSet()); |
| 708 | 817 | } |
| 709 | 818 | |
| 710 | | const rendered = buffer.toOwnedSlice(); |
| 711 | | errdefer dg.typedefs.allocator.free(rendered); |
| 712 | | const name = rendered[name_index .. rendered.len - 2]; |
| 819 | const name = dg.getTypedefName(t) orelse |
| 820 | try dg.renderErrorUnionTypedef(t); |
| 713 | 821 | |
| 714 | | try dg.typedefs.ensureUnusedCapacity(1); |
| 715 | | try w.writeAll(name); |
| 716 | | dg.typedefs.putAssumeCapacityNoClobber( |
| 717 | | try t.copy(dg.typedefs_arena), |
| 718 | | .{ .name = name, .rendered = rendered }, |
| 719 | | ); |
| 822 | return w.writeAll(name); |
| 720 | 823 | }, |
| 721 | 824 | .Struct => { |
| 722 | | if (dg.typedefs.get(t)) |some| { |
| 723 | | return w.writeAll(some.name); |
| 724 | | } |
| 725 | | const struct_obj = t.castTag(.@"struct").?.data; // Handle 0 bit types elsewhere. |
| 726 | | const fqn = try struct_obj.getFullyQualifiedName(dg.typedefs.allocator); |
| 727 | | defer dg.typedefs.allocator.free(fqn); |
| 728 | | |
| 729 | | var buffer = std.ArrayList(u8).init(dg.typedefs.allocator); |
| 730 | | defer buffer.deinit(); |
| 731 | | |
| 732 | | try buffer.appendSlice("typedef struct {\n"); |
| 733 | | { |
| 734 | | var it = struct_obj.fields.iterator(); |
| 735 | | while (it.next()) |entry| { |
| 736 | | const field_ty = entry.value_ptr.ty; |
| 737 | | const name: CValue = .{ .bytes = entry.key_ptr.* }; |
| 738 | | try buffer.append(' '); |
| 739 | | try dg.renderTypeAndName(buffer.writer(), field_ty, name, .Mut); |
| 740 | | try buffer.appendSlice(";\n"); |
| 741 | | } |
| 742 | | } |
| 743 | | try buffer.appendSlice("} "); |
| 744 | | |
| 745 | | const name_start = buffer.items.len; |
| 746 | | try buffer.writer().print("zig_S_{s};\n", .{fmtIdent(fqn)}); |
| 825 | const name = dg.getTypedefName(t) orelse |
| 826 | try dg.renderStructTypedef(t); |
| 747 | 827 | |
| 748 | | const rendered = buffer.toOwnedSlice(); |
| 749 | | errdefer dg.typedefs.allocator.free(rendered); |
| 750 | | const name = rendered[name_start .. rendered.len - 2]; |
| 751 | | |
| 752 | | try dg.typedefs.ensureUnusedCapacity(1); |
| 753 | | try w.writeAll(name); |
| 754 | | dg.typedefs.putAssumeCapacityNoClobber( |
| 755 | | try t.copy(dg.typedefs_arena), |
| 756 | | .{ .name = name, .rendered = rendered }, |
| 757 | | ); |
| 828 | return w.writeAll(name); |
| 758 | 829 | }, |
| 759 | 830 | .Enum => { |
| 760 | 831 | // For enums, we simply use the integer tag type. |
| ... | ... | @@ -763,12 +834,17 @@ pub const DeclGen = struct { |
| 763 | 834 | |
| 764 | 835 | try dg.renderType(w, int_tag_ty); |
| 765 | 836 | }, |
| 766 | | .Union => return dg.fail("TODO: C backend: implement type Union", .{}), |
| 837 | |
| 838 | .Union, |
| 839 | .Frame, |
| 840 | .AnyFrame, |
| 841 | .Vector, |
| 842 | .Opaque, |
| 843 | => |tag| return dg.fail("TODO: C backend: implement value of type {s}", .{ |
| 844 | @tagName(tag), |
| 845 | }), |
| 846 | |
| 767 | 847 | .Fn => unreachable, // This is a function body, not a function pointer. |
| 768 | | .Opaque => return dg.fail("TODO: C backend: implement type Opaque", .{}), |
| 769 | | .Frame => return dg.fail("TODO: C backend: implement type Frame", .{}), |
| 770 | | .AnyFrame => return dg.fail("TODO: C backend: implement type AnyFrame", .{}), |
| 771 | | .Vector => return dg.fail("TODO: C backend: implement type Vector", .{}), |
| 772 | 848 | |
| 773 | 849 | .Null, |
| 774 | 850 | .Undefined, |
| ... | ... | @@ -800,100 +876,14 @@ pub const DeclGen = struct { |
| 800 | 876 | render_ty = render_ty.elemType(); |
| 801 | 877 | } |
| 802 | 878 | |
| 803 | | // TODO this is duplicated from the code below and does not handle |
| 804 | | // arbitrary nesting of pointers. This renderTypeAndName function |
| 805 | | // needs to be reworked by someone who understands C's insane type syntax. That |
| 806 | | // person might be future me but it is certainly not present me. |
| 807 | | if (render_ty.zigTypeTag() == .Pointer and |
| 808 | | render_ty.childType().zigTypeTag() == .Pointer and |
| 809 | | render_ty.childType().childType().zigTypeTag() == .Fn) |
| 810 | | { |
| 811 | | const ptr2_ty = render_ty.childType(); |
| 812 | | const fn_info = ptr2_ty.childType().fnInfo(); |
| 813 | | const ret_ty = fn_info.return_type; |
| 814 | | if (ret_ty.zigTypeTag() == .NoReturn) { |
| 815 | | // noreturn attribute is not allowed here. |
| 816 | | try w.writeAll("void"); |
| 817 | | } else { |
| 818 | | try dg.renderType(w, ret_ty); |
| 819 | | } |
| 820 | | try w.writeAll(" (*"); |
| 821 | | switch (mutability) { |
| 822 | | .Const => try w.writeAll("const "), |
| 823 | | .Mut => {}, |
| 824 | | } |
| 825 | | if (!ptr2_ty.ptrIsMutable()) { |
| 826 | | try w.writeAll("*const "); |
| 827 | | } else { |
| 828 | | try w.writeAll("*"); |
| 829 | | } |
| 830 | | try dg.writeCValue(w, name); |
| 831 | | try w.writeAll(")("); |
| 832 | | const param_len = fn_info.param_types.len; |
| 833 | | const is_var_args = fn_info.is_var_args; |
| 834 | | if (param_len == 0 and !is_var_args) |
| 835 | | try w.writeAll("void") |
| 836 | | else { |
| 837 | | var index: usize = 0; |
| 838 | | while (index < param_len) : (index += 1) { |
| 839 | | if (index > 0) { |
| 840 | | try w.writeAll(", "); |
| 841 | | } |
| 842 | | try dg.renderType(w, fn_info.param_types[index]); |
| 843 | | } |
| 844 | | } |
| 845 | | if (is_var_args) { |
| 846 | | if (param_len != 0) try w.writeAll(", "); |
| 847 | | try w.writeAll("..."); |
| 848 | | } |
| 849 | | try w.writeByte(')'); |
| 850 | | return; |
| 851 | | } |
| 879 | try dg.renderType(w, render_ty); |
| 852 | 880 | |
| 853 | | if (render_ty.castPtrToFn()) |fn_ty| { |
| 854 | | const fn_info = fn_ty.fnInfo(); |
| 855 | | const ret_ty = fn_info.return_type; |
| 856 | | if (ret_ty.zigTypeTag() == .NoReturn) { |
| 857 | | // noreturn attribute is not allowed here. |
| 858 | | try w.writeAll("void"); |
| 859 | | } else { |
| 860 | | try dg.renderType(w, ret_ty); |
| 861 | | } |
| 862 | | try w.writeAll(" (*"); |
| 863 | | switch (mutability) { |
| 864 | | .Const => try w.writeAll("const "), |
| 865 | | .Mut => {}, |
| 866 | | } |
| 867 | | try dg.writeCValue(w, name); |
| 868 | | try w.writeAll(")("); |
| 869 | | const param_len = fn_info.param_types.len; |
| 870 | | const is_var_args = fn_info.is_var_args; |
| 871 | | if (param_len == 0 and !is_var_args) |
| 872 | | try w.writeAll("void") |
| 873 | | else { |
| 874 | | var index: usize = 0; |
| 875 | | while (index < param_len) : (index += 1) { |
| 876 | | if (index > 0) { |
| 877 | | try w.writeAll(", "); |
| 878 | | } |
| 879 | | try dg.renderType(w, fn_info.param_types[index]); |
| 880 | | } |
| 881 | | } |
| 882 | | if (is_var_args) { |
| 883 | | if (param_len != 0) try w.writeAll(", "); |
| 884 | | try w.writeAll("..."); |
| 885 | | } |
| 886 | | try w.writeByte(')'); |
| 887 | | } else { |
| 888 | | try dg.renderType(w, render_ty); |
| 889 | | |
| 890 | | const const_prefix = switch (mutability) { |
| 891 | | .Const => "const ", |
| 892 | | .Mut => "", |
| 893 | | }; |
| 894 | | try w.print(" {s}", .{const_prefix}); |
| 895 | | try dg.writeCValue(w, name); |
| 896 | | } |
| 881 | const const_prefix = switch (mutability) { |
| 882 | .Const => "const ", |
| 883 | .Mut => "", |
| 884 | }; |
| 885 | try w.print(" {s}", .{const_prefix}); |
| 886 | try dg.writeCValue(w, name); |
| 897 | 887 | try w.writeAll(suffix.items); |
| 898 | 888 | } |
| 899 | 889 | |
| ... | ... | @@ -1224,10 +1214,11 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO |
| 1224 | 1214 | fn airSliceField(f: *Function, inst: Air.Inst.Index, suffix: []const u8) !CValue { |
| 1225 | 1215 | if (f.liveness.isUnused(inst)) return CValue.none; |
| 1226 | 1216 | |
| 1217 | const inst_ty = f.air.typeOfIndex(inst); |
| 1227 | 1218 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; |
| 1228 | 1219 | const operand = try f.resolveInst(ty_op.operand); |
| 1229 | 1220 | const writer = f.object.writer(); |
| 1230 | | const local = try f.allocLocal(Type.initTag(.usize), .Const); |
| 1221 | const local = try f.allocLocal(inst_ty, .Const); |
| 1231 | 1222 | try writer.writeAll(" = "); |
| 1232 | 1223 | try f.writeCValue(writer, operand); |
| 1233 | 1224 | try writer.writeAll(suffix); |