| ... | ... | @@ -558,6 +558,8 @@ pub const Object = struct { |
| 558 | 558 | val: InternPool.Index, |
| 559 | 559 | @"addrspace": std.builtin.AddressSpace, |
| 560 | 560 | }, Builder.Variable.Index), |
| 561 | /// Maps restricted types to supporting decls. |
| 562 | restricted_map: std.array_hash_map.Auto(InternPool.Index, RestrictedDecls), |
| 561 | 563 | /// Maps enum types to their corresponding LLVM functions for implementing the `tag_name` instruction. |
| 562 | 564 | enum_tag_name_map: std.AutoHashMapUnmanaged(InternPool.Index, Builder.Function.Index), |
| 563 | 565 | /// Serves the same purpose as `enum_tag_name_map` but for the `is_named_enum_value` instruction. |
| ... | ... | @@ -666,6 +668,7 @@ pub const Object = struct { |
| 666 | 668 | .zcu = zcu, |
| 667 | 669 | .nav_map = .empty, |
| 668 | 670 | .uav_map = .empty, |
| 671 | .restricted_map = .empty, |
| 669 | 672 | .enum_tag_name_map = .empty, |
| 670 | 673 | .named_enum_map = .empty, |
| 671 | 674 | .type_map = .empty, |
| ... | ... | @@ -686,6 +689,8 @@ pub const Object = struct { |
| 686 | 689 | self.debug_types.deinit(gpa); |
| 687 | 690 | self.nav_map.deinit(gpa); |
| 688 | 691 | self.uav_map.deinit(gpa); |
| 692 | for (self.restricted_map.values()) |*value| value.deinit(gpa); |
| 693 | self.restricted_map.deinit(gpa); |
| 689 | 694 | self.enum_tag_name_map.deinit(gpa); |
| 690 | 695 | self.named_enum_map.deinit(gpa); |
| 691 | 696 | self.type_map.deinit(gpa); |
| ... | ... | @@ -693,6 +698,65 @@ pub const Object = struct { |
| 693 | 698 | self.* = undefined; |
| 694 | 699 | } |
| 695 | 700 | |
| 701 | const RestrictedDecls = struct { |
| 702 | len: Builder.Variable.Index, |
| 703 | array: Builder.Variable.Index, |
| 704 | values: std.array_hash_map.Auto(InternPool.Index, Builder.Constant), |
| 705 | |
| 706 | fn deinit(rd: *RestrictedDecls, gpa: Allocator) void { |
| 707 | rd.values.deinit(gpa); |
| 708 | rd.* = undefined; |
| 709 | } |
| 710 | }; |
| 711 | pub fn getRestrictedDecls(o: *Object, ty: Type) Allocator.Error!*RestrictedDecls { |
| 712 | const gop = try o.restricted_map.getOrPut(o.gpa, ty.toIntern()); |
| 713 | if (gop.found_existing) return gop.value_ptr; |
| 714 | errdefer _ = o.restricted_map.pop().?; |
| 715 | |
| 716 | const target = o.zcu.getTarget(); |
| 717 | const ip = &o.zcu.intern_pool; |
| 718 | const ptr_align = Type.ptrAbiAlignment(target).toLlvm(); |
| 719 | |
| 720 | const ty_name = ty.containerTypeName(ip).toSlice(ip); |
| 721 | gop.value_ptr.* = .{ |
| 722 | .len = try o.builder.addVariable( |
| 723 | try o.builder.strtabStringFmt("{s}.len", .{ty_name}), |
| 724 | try o.lowerType(.usize), |
| 725 | .default, |
| 726 | ), |
| 727 | .array = try o.builder.addVariable( |
| 728 | try o.builder.strtabString(ty_name), |
| 729 | .void, |
| 730 | .default, |
| 731 | ), |
| 732 | .values = .empty, |
| 733 | }; |
| 734 | gop.value_ptr.len.setLinkage(.private, &o.builder); |
| 735 | gop.value_ptr.len.setMutability(.constant, &o.builder); |
| 736 | gop.value_ptr.len.setAlignment(ptr_align, &o.builder); |
| 737 | gop.value_ptr.len.setUnnamedAddr(.unnamed_addr, &o.builder); |
| 738 | gop.value_ptr.array.setLinkage(.private, &o.builder); |
| 739 | gop.value_ptr.array.setMutability(.constant, &o.builder); |
| 740 | gop.value_ptr.array.setAlignment(ptr_align, &o.builder); |
| 741 | // Setting unnamed_addr here would reduce safety, and the module emitting the safety checks may not be the same module |
| 742 | // that defined the restricted type. In any case, llvm will add unnamed_addr itself if no safety checks end up being emitted. |
| 743 | gop.value_ptr.array.setUnnamedAddr(.default, &o.builder); |
| 744 | return gop.value_ptr; |
| 745 | } |
| 746 | fn genRestrictedDecls(o: *Object) Allocator.Error!void { |
| 747 | for (o.restricted_map.values()) |restricted_decls| { |
| 748 | const len = restricted_decls.values.count(); |
| 749 | try restricted_decls.len.setInitializer( |
| 750 | try o.builder.intConst(restricted_decls.len.typeOf(&o.builder), len), |
| 751 | &o.builder, |
| 752 | ); |
| 753 | try restricted_decls.array.setInitializer(try o.builder.arrayConst( |
| 754 | try o.builder.arrayType(len, .ptr), |
| 755 | restricted_decls.values.values(), |
| 756 | ), &o.builder); |
| 757 | } |
| 758 | } |
| 759 | |
| 696 | 760 | fn genErrorNameTable(o: *Object) Allocator.Error!void { |
| 697 | 761 | // If o.error_name_table is null, then it was not referenced by any instructions. |
| 698 | 762 | if (o.error_name_table == .none) return; |
| ... | ... | @@ -771,6 +835,7 @@ pub const Object = struct { |
| 771 | 835 | const diags = &comp.link_diags; |
| 772 | 836 | |
| 773 | 837 | { |
| 838 | try o.genRestrictedDecls(); |
| 774 | 839 | if (o.errors_len_variable != .none) { |
| 775 | 840 | const errors_len = zcu.intern_pool.global_error_set.getNamesFromMainThread().len; |
| 776 | 841 | const init_val = try o.builder.intConst(try o.errorIntType(), errors_len); |
| ... | ... | @@ -2006,55 +2071,64 @@ pub const Object = struct { |
| 2006 | 2071 | .pointer => { |
| 2007 | 2072 | const ptr_size = Type.ptrAbiSize(zcu.getTarget()); |
| 2008 | 2073 | const ptr_align = Type.ptrAbiAlignment(zcu.getTarget()); |
| 2009 | | |
| 2010 | | if (ty.isSlice(zcu)) { |
| 2011 | | const debug_ptr_type = try o.builder.debugMemberType( |
| 2012 | | try o.builder.metadataString("ptr"), |
| 2074 | switch (ty.restrictedRepr(zcu)) { |
| 2075 | .indirect => return o.builder.debugPointerType( |
| 2076 | name, |
| 2013 | 2077 | null, // file |
| 2014 | | ty_fwd_ref, |
| 2078 | o.debug_compile_unit.unwrap().?, // scope |
| 2015 | 2079 | 0, // line |
| 2016 | | try o.getDebugType(pt, ty.slicePtrFieldType(zcu)), |
| 2080 | try o.getDebugType(pt, ty.unrestrictedType(zcu).?), |
| 2017 | 2081 | ptr_size * 8, |
| 2018 | 2082 | ptr_align.toByteUnits().? * 8, |
| 2019 | 2083 | 0, // offset |
| 2020 | | ); |
| 2084 | ), |
| 2085 | .direct => if (ty.isSlice(zcu)) { |
| 2086 | const debug_ptr_type = try o.builder.debugMemberType( |
| 2087 | try o.builder.metadataString("ptr"), |
| 2088 | null, // file |
| 2089 | ty_fwd_ref, |
| 2090 | 0, // line |
| 2091 | try o.getDebugType(pt, ty.slicePtrFieldType(zcu)), |
| 2092 | ptr_size * 8, |
| 2093 | ptr_align.toByteUnits().? * 8, |
| 2094 | 0, // offset |
| 2095 | ); |
| 2021 | 2096 | |
| 2022 | | const debug_len_type = try o.builder.debugMemberType( |
| 2023 | | try o.builder.metadataString("len"), |
| 2024 | | null, // file |
| 2025 | | ty_fwd_ref, |
| 2026 | | 0, // line |
| 2027 | | try o.getDebugType(pt, .usize), |
| 2028 | | ptr_size * 8, |
| 2029 | | ptr_align.toByteUnits().? * 8, |
| 2030 | | ptr_size * 8, |
| 2031 | | ); |
| 2097 | const debug_len_type = try o.builder.debugMemberType( |
| 2098 | try o.builder.metadataString("len"), |
| 2099 | null, // file |
| 2100 | ty_fwd_ref, |
| 2101 | 0, // line |
| 2102 | try o.getDebugType(pt, .usize), |
| 2103 | ptr_size * 8, |
| 2104 | ptr_align.toByteUnits().? * 8, |
| 2105 | ptr_size * 8, |
| 2106 | ); |
| 2032 | 2107 | |
| 2033 | | return o.builder.debugStructType( |
| 2108 | return o.builder.debugStructType( |
| 2109 | name, |
| 2110 | null, // file |
| 2111 | o.debug_compile_unit.unwrap().?, // scope |
| 2112 | 0, // line |
| 2113 | null, // underlying type |
| 2114 | ptr_size * 2 * 8, |
| 2115 | ptr_align.toByteUnits().? * 8, |
| 2116 | try o.builder.metadataTuple(&.{ |
| 2117 | debug_ptr_type, |
| 2118 | debug_len_type, |
| 2119 | }), |
| 2120 | ); |
| 2121 | } else return o.builder.debugPointerType( |
| 2034 | 2122 | name, |
| 2035 | 2123 | null, // file |
| 2036 | 2124 | o.debug_compile_unit.unwrap().?, // scope |
| 2037 | 2125 | 0, // line |
| 2038 | | null, // underlying type |
| 2039 | | ptr_size * 2 * 8, |
| 2126 | try o.getDebugType(pt, ty.childType(zcu)), |
| 2127 | ptr_size * 8, |
| 2040 | 2128 | ptr_align.toByteUnits().? * 8, |
| 2041 | | try o.builder.metadataTuple(&.{ |
| 2042 | | debug_ptr_type, |
| 2043 | | debug_len_type, |
| 2044 | | }), |
| 2045 | | ); |
| 2129 | 0, // offset |
| 2130 | ), |
| 2046 | 2131 | } |
| 2047 | | |
| 2048 | | return o.builder.debugPointerType( |
| 2049 | | name, |
| 2050 | | null, // file |
| 2051 | | o.debug_compile_unit.unwrap().?, // scope |
| 2052 | | 0, // line |
| 2053 | | try o.getDebugType(pt, ty.childType(zcu)), |
| 2054 | | ptr_size * 8, |
| 2055 | | ptr_align.toByteUnits().? * 8, |
| 2056 | | 0, // offset |
| 2057 | | ); |
| 2058 | 2132 | }, |
| 2059 | 2133 | .array => return o.builder.debugArrayType( |
| 2060 | 2134 | name, |
| ... | ... | @@ -3047,7 +3121,7 @@ pub const Object = struct { |
| 3047 | 3121 | .empty_tuple, |
| 3048 | 3122 | .none, |
| 3049 | 3123 | => unreachable, |
| 3050 | | else => switch (ip.indexToKey(t.toIntern())) { |
| 3124 | else => t: switch (ip.indexToKey(t.toIntern())) { |
| 3051 | 3125 | .int_type => |int_type| try o.builder.intType(int_type.bits), |
| 3052 | 3126 | .ptr_type => |ptr_type| type: { |
| 3053 | 3127 | const ptr_ty = try o.builder.ptrType( |
| ... | ... | @@ -3061,7 +3135,10 @@ pub const Object = struct { |
| 3061 | 3135 | }), |
| 3062 | 3136 | }; |
| 3063 | 3137 | }, |
| 3064 | | .restricted_ptr_type => @panic("TODO implement restricted pointers"), |
| 3138 | .restricted_ptr_type => |restricted_ptr_type| switch (t.restrictedRepr(zcu)) { |
| 3139 | .indirect => .ptr, |
| 3140 | .direct => continue :t .{ .ptr_type = ip.indexToKey(restricted_ptr_type.unrestricted_ptr_type).ptr_type }, |
| 3141 | }, |
| 3065 | 3142 | .array_type => |array_type| o.builder.arrayType( |
| 3066 | 3143 | array_type.lenIncludingSentinel(), |
| 3067 | 3144 | try o.lowerType(.fromInterned(array_type.child)), |
| ... | ... | @@ -3545,7 +3622,27 @@ pub const Object = struct { |
| 3545 | 3622 | 128 => try o.builder.fp128Const(val.toFloat(f128, zcu)), |
| 3546 | 3623 | else => unreachable, |
| 3547 | 3624 | }, |
| 3548 | | .ptr => try o.lowerPtr(arg_val, 0), |
| 3625 | .ptr => switch (ty.restrictedRepr(zcu)) { |
| 3626 | .indirect => { |
| 3627 | const restricted_decls = try o.getRestrictedDecls(ty); |
| 3628 | const gop = try restricted_decls.values.getOrPut(o.gpa, arg_val); |
| 3629 | if (!gop.found_existing) gop.value_ptr.* = try o.lowerValue(try ip.getCoerced( |
| 3630 | zcu.gpa, |
| 3631 | zcu.comp.io, |
| 3632 | .main, // FIXME |
| 3633 | arg_val, |
| 3634 | ty.unrestrictedType(zcu).?.toIntern(), |
| 3635 | )); |
| 3636 | return o.builder.gepConst( |
| 3637 | .inbounds, |
| 3638 | .ptr, |
| 3639 | restricted_decls.array.toConst(&o.builder), |
| 3640 | null, |
| 3641 | &.{try o.builder.intConst(.i64, gop.index)}, |
| 3642 | ); |
| 3643 | }, |
| 3644 | .direct => try o.lowerPtr(arg_val, 0), |
| 3645 | }, |
| 3549 | 3646 | .slice => |slice| return o.builder.structConst(try o.lowerType(ty), &.{ |
| 3550 | 3647 | try o.lowerValue(slice.ptr), |
| 3551 | 3648 | try o.lowerValue(slice.len), |