| ... | @@ -558,6 +558,8 @@ pub const Object = struct { | ... | @@ -558,6 +558,8 @@ pub const Object = struct { |
| 558 | val: InternPool.Index, | 558 | val: InternPool.Index, |
| 559 | @"addrspace": std.builtin.AddressSpace, | 559 | @"addrspace": std.builtin.AddressSpace, |
| 560 | }, Builder.Variable.Index), | 560 | }, Builder.Variable.Index), |
| | 561 | /// Maps restricted types to supporting decls. |
| | 562 | restricted_map: std.array_hash_map.Auto(InternPool.Index, RestrictedDecls), |
| 561 | /// Maps enum types to their corresponding LLVM functions for implementing the `tag_name` instruction. | 563 | /// Maps enum types to their corresponding LLVM functions for implementing the `tag_name` instruction. |
| 562 | enum_tag_name_map: std.AutoHashMapUnmanaged(InternPool.Index, Builder.Function.Index), | 564 | enum_tag_name_map: std.AutoHashMapUnmanaged(InternPool.Index, Builder.Function.Index), |
| 563 | /// Serves the same purpose as `enum_tag_name_map` but for the `is_named_enum_value` instruction. | 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,6 +668,7 @@ pub const Object = struct { |
| 666 | .zcu = zcu, | 668 | .zcu = zcu, |
| 667 | .nav_map = .empty, | 669 | .nav_map = .empty, |
| 668 | .uav_map = .empty, | 670 | .uav_map = .empty, |
| | 671 | .restricted_map = .empty, |
| 669 | .enum_tag_name_map = .empty, | 672 | .enum_tag_name_map = .empty, |
| 670 | .named_enum_map = .empty, | 673 | .named_enum_map = .empty, |
| 671 | .type_map = .empty, | 674 | .type_map = .empty, |
| ... | @@ -686,6 +689,8 @@ pub const Object = struct { | ... | @@ -686,6 +689,8 @@ pub const Object = struct { |
| 686 | self.debug_types.deinit(gpa); | 689 | self.debug_types.deinit(gpa); |
| 687 | self.nav_map.deinit(gpa); | 690 | self.nav_map.deinit(gpa); |
| 688 | self.uav_map.deinit(gpa); | 691 | self.uav_map.deinit(gpa); |
| | 692 | for (self.restricted_map.values()) |*value| value.deinit(gpa); |
| | 693 | self.restricted_map.deinit(gpa); |
| 689 | self.enum_tag_name_map.deinit(gpa); | 694 | self.enum_tag_name_map.deinit(gpa); |
| 690 | self.named_enum_map.deinit(gpa); | 695 | self.named_enum_map.deinit(gpa); |
| 691 | self.type_map.deinit(gpa); | 696 | self.type_map.deinit(gpa); |
| ... | @@ -693,6 +698,65 @@ pub const Object = struct { | ... | @@ -693,6 +698,65 @@ pub const Object = struct { |
| 693 | self.* = undefined; | 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 | fn genErrorNameTable(o: *Object) Allocator.Error!void { | 760 | fn genErrorNameTable(o: *Object) Allocator.Error!void { |
| 697 | // If o.error_name_table is null, then it was not referenced by any instructions. | 761 | // If o.error_name_table is null, then it was not referenced by any instructions. |
| 698 | if (o.error_name_table == .none) return; | 762 | if (o.error_name_table == .none) return; |
| ... | @@ -771,6 +835,7 @@ pub const Object = struct { | ... | @@ -771,6 +835,7 @@ pub const Object = struct { |
| 771 | const diags = &comp.link_diags; | 835 | const diags = &comp.link_diags; |
| 772 | | 836 | |
| 773 | { | 837 | { |
| | 838 | try o.genRestrictedDecls(); |
| 774 | if (o.errors_len_variable != .none) { | 839 | if (o.errors_len_variable != .none) { |
| 775 | const errors_len = zcu.intern_pool.global_error_set.getNamesFromMainThread().len; | 840 | const errors_len = zcu.intern_pool.global_error_set.getNamesFromMainThread().len; |
| 776 | const init_val = try o.builder.intConst(try o.errorIntType(), errors_len); | 841 | const init_val = try o.builder.intConst(try o.errorIntType(), errors_len); |
| ... | @@ -2006,55 +2071,64 @@ pub const Object = struct { | ... | @@ -2006,55 +2071,64 @@ pub const Object = struct { |
| 2006 | .pointer => { | 2071 | .pointer => { |
| 2007 | const ptr_size = Type.ptrAbiSize(zcu.getTarget()); | 2072 | const ptr_size = Type.ptrAbiSize(zcu.getTarget()); |
| 2008 | const ptr_align = Type.ptrAbiAlignment(zcu.getTarget()); | 2073 | const ptr_align = Type.ptrAbiAlignment(zcu.getTarget()); |
| 2009 | | 2074 | switch (ty.restrictedRepr(zcu)) { |
| 2010 | if (ty.isSlice(zcu)) { | 2075 | .indirect => return o.builder.debugPointerType( |
| 2011 | const debug_ptr_type = try o.builder.debugMemberType( | 2076 | name, |
| 2012 | try o.builder.metadataString("ptr"), | | |
| 2013 | null, // file | 2077 | null, // file |
| 2014 | ty_fwd_ref, | 2078 | o.debug_compile_unit.unwrap().?, // scope |
| 2015 | 0, // line | 2079 | 0, // line |
| 2016 | try o.getDebugType(pt, ty.slicePtrFieldType(zcu)), | 2080 | try o.getDebugType(pt, ty.unrestrictedType(zcu).?), |
| 2017 | ptr_size * 8, | 2081 | ptr_size * 8, |
| 2018 | ptr_align.toByteUnits().? * 8, | 2082 | ptr_align.toByteUnits().? * 8, |
| 2019 | 0, // offset | 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( | 2097 | const debug_len_type = try o.builder.debugMemberType( |
| 2023 | try o.builder.metadataString("len"), | 2098 | try o.builder.metadataString("len"), |
| 2024 | null, // file | 2099 | null, // file |
| 2025 | ty_fwd_ref, | 2100 | ty_fwd_ref, |
| 2026 | 0, // line | 2101 | 0, // line |
| 2027 | try o.getDebugType(pt, .usize), | 2102 | try o.getDebugType(pt, .usize), |
| 2028 | ptr_size * 8, | 2103 | ptr_size * 8, |
| 2029 | ptr_align.toByteUnits().? * 8, | 2104 | ptr_align.toByteUnits().? * 8, |
| 2030 | ptr_size * 8, | 2105 | ptr_size * 8, |
| 2031 | ); | 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 | name, | 2122 | name, |
| 2035 | null, // file | 2123 | null, // file |
| 2036 | o.debug_compile_unit.unwrap().?, // scope | 2124 | o.debug_compile_unit.unwrap().?, // scope |
| 2037 | 0, // line | 2125 | 0, // line |
| 2038 | null, // underlying type | 2126 | try o.getDebugType(pt, ty.childType(zcu)), |
| 2039 | ptr_size * 2 * 8, | 2127 | ptr_size * 8, |
| 2040 | ptr_align.toByteUnits().? * 8, | 2128 | ptr_align.toByteUnits().? * 8, |
| 2041 | try o.builder.metadataTuple(&.{ | 2129 | 0, // offset |
| 2042 | debug_ptr_type, | 2130 | ), |
| 2043 | debug_len_type, | | |
| 2044 | }), | | |
| 2045 | ); | | |
| 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 | .array => return o.builder.debugArrayType( | 2133 | .array => return o.builder.debugArrayType( |
| 2060 | name, | 2134 | name, |
| ... | @@ -3047,7 +3121,7 @@ pub const Object = struct { | ... | @@ -3047,7 +3121,7 @@ pub const Object = struct { |
| 3047 | .empty_tuple, | 3121 | .empty_tuple, |
| 3048 | .none, | 3122 | .none, |
| 3049 | => unreachable, | 3123 | => unreachable, |
| 3050 | else => switch (ip.indexToKey(t.toIntern())) { | 3124 | else => t: switch (ip.indexToKey(t.toIntern())) { |
| 3051 | .int_type => |int_type| try o.builder.intType(int_type.bits), | 3125 | .int_type => |int_type| try o.builder.intType(int_type.bits), |
| 3052 | .ptr_type => |ptr_type| type: { | 3126 | .ptr_type => |ptr_type| type: { |
| 3053 | const ptr_ty = try o.builder.ptrType( | 3127 | const ptr_ty = try o.builder.ptrType( |
| ... | @@ -3061,7 +3135,10 @@ pub const Object = struct { | ... | @@ -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 | .array_type => |array_type| o.builder.arrayType( | 3142 | .array_type => |array_type| o.builder.arrayType( |
| 3066 | array_type.lenIncludingSentinel(), | 3143 | array_type.lenIncludingSentinel(), |
| 3067 | try o.lowerType(.fromInterned(array_type.child)), | 3144 | try o.lowerType(.fromInterned(array_type.child)), |
| ... | @@ -3545,7 +3622,27 @@ pub const Object = struct { | ... | @@ -3545,7 +3622,27 @@ pub const Object = struct { |
| 3545 | 128 => try o.builder.fp128Const(val.toFloat(f128, zcu)), | 3622 | 128 => try o.builder.fp128Const(val.toFloat(f128, zcu)), |
| 3546 | else => unreachable, | 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 | .slice => |slice| return o.builder.structConst(try o.lowerType(ty), &.{ | 3646 | .slice => |slice| return o.builder.structConst(try o.lowerType(ty), &.{ |
| 3550 | try o.lowerValue(slice.ptr), | 3647 | try o.lowerValue(slice.ptr), |
| 3551 | try o.lowerValue(slice.len), | 3648 | try o.lowerValue(slice.len), |