| author | |
| committer | |
| log | 0bf8617d963dc432ed0204b10285cc414becf2fd |
| tree | b4a28f10bd66183cd949e6f0fbb4a786bfc1aa04 |
| parent | 178ee8aef1b9f765da916f3e1e4cab66437f8e0a |
46 files changed, 1910 insertions(+), 1666 deletions(-)
CMakeLists.txt+1-1| ... | @@ -519,6 +519,7 @@ set(ZIG_STAGE2_SOURCES | ... | @@ -519,6 +519,7 @@ set(ZIG_STAGE2_SOURCES |
| 519 | src/Air/Legalize.zig | 519 | src/Air/Legalize.zig |
| 520 | src/Air/Liveness.zig | 520 | src/Air/Liveness.zig |
| 521 | src/Air/Liveness/Verify.zig | 521 | src/Air/Liveness/Verify.zig |
| 522 | src/Air/print.zig | ||
| 522 | src/Air/types_resolved.zig | 523 | src/Air/types_resolved.zig |
| 523 | src/Builtin.zig | 524 | src/Builtin.zig |
| 524 | src/Compilation.zig | 525 | src/Compilation.zig |
| ... | @@ -675,7 +676,6 @@ set(ZIG_STAGE2_SOURCES | ... | @@ -675,7 +676,6 @@ set(ZIG_STAGE2_SOURCES |
| 675 | src/libs/mingw.zig | 676 | src/libs/mingw.zig |
| 676 | src/libs/musl.zig | 677 | src/libs/musl.zig |
| 677 | src/mutable_value.zig | 678 | src/mutable_value.zig |
| 678 | src/print_air.zig | ||
| 679 | src/print_env.zig | 679 | src/print_env.zig |
| 680 | src/print_targets.zig | 680 | src/print_targets.zig |
| 681 | src/print_value.zig | 681 | src/print_value.zig |
lib/std/builtin.zig+13-2| ... | @@ -61,7 +61,7 @@ pub const StackTrace = struct { | ... | @@ -61,7 +61,7 @@ pub const StackTrace = struct { |
| 61 | 61 | ||
| 62 | /// This data structure is used by the Zig language code generation and | 62 | /// This data structure is used by the Zig language code generation and |
| 63 | /// therefore must be kept in sync with the compiler implementation. | 63 | /// therefore must be kept in sync with the compiler implementation. |
| 64 | pub const GlobalLinkage = enum { | 64 | pub const GlobalLinkage = enum(u2) { |
| 65 | internal, | 65 | internal, |
| 66 | strong, | 66 | strong, |
| 67 | weak, | 67 | weak, |
| ... | @@ -70,7 +70,7 @@ pub const GlobalLinkage = enum { | ... | @@ -70,7 +70,7 @@ pub const GlobalLinkage = enum { |
| 70 | 70 | ||
| 71 | /// This data structure is used by the Zig language code generation and | 71 | /// This data structure is used by the Zig language code generation and |
| 72 | /// therefore must be kept in sync with the compiler implementation. | 72 | /// therefore must be kept in sync with the compiler implementation. |
| 73 | pub const SymbolVisibility = enum { | 73 | pub const SymbolVisibility = enum(u2) { |
| 74 | default, | 74 | default, |
| 75 | hidden, | 75 | hidden, |
| 76 | protected, | 76 | protected, |
| ... | @@ -1030,8 +1030,19 @@ pub const ExternOptions = struct { | ... | @@ -1030,8 +1030,19 @@ pub const ExternOptions = struct { |
| 1030 | name: []const u8, | 1030 | name: []const u8, |
| 1031 | library_name: ?[]const u8 = null, | 1031 | library_name: ?[]const u8 = null, |
| 1032 | linkage: GlobalLinkage = .strong, | 1032 | linkage: GlobalLinkage = .strong, |
| 1033 | visibility: SymbolVisibility = .default, | ||
| 1034 | /// Setting this to `true` makes the `@extern` a runtime value. | ||
| 1033 | is_thread_local: bool = false, | 1035 | is_thread_local: bool = false, |
| 1034 | is_dll_import: bool = false, | 1036 | is_dll_import: bool = false, |
| 1037 | relocation: Relocation = .any, | ||
| 1038 | |||
| 1039 | pub const Relocation = enum(u1) { | ||
| 1040 | /// Any type of relocation is allowed. | ||
| 1041 | any, | ||
| 1042 | /// A program-counter-relative relocation is required. | ||
| 1043 | /// Using this value makes the `@extern` a runtime value. | ||
| 1044 | pcrel, | ||
| 1045 | }; | ||
| 1035 | }; | 1046 | }; |
| 1036 | 1047 | ||
| 1037 | /// This data structure is used by the Zig language code generation and | 1048 | /// This data structure is used by the Zig language code generation and |
lib/std/dynamic_library.zig+8-5| ... | @@ -83,13 +83,16 @@ const RDebug = extern struct { | ... | @@ -83,13 +83,16 @@ const RDebug = extern struct { |
| 83 | r_ldbase: usize, | 83 | r_ldbase: usize, |
| 84 | }; | 84 | }; |
| 85 | 85 | ||
| 86 | /// TODO make it possible to reference this same external symbol 2x so we don't need this | 86 | /// TODO fix comparisons of extern symbol pointers so we don't need this helper function. |
| 87 | /// helper function. | 87 | pub fn get_DYNAMIC() ?[*]const elf.Dyn { |
| 88 | pub fn get_DYNAMIC() ?[*]elf.Dyn { | 88 | return @extern([*]const elf.Dyn, .{ |
| 89 | return @extern([*]elf.Dyn, .{ .name = "_DYNAMIC", .linkage = .weak }); | 89 | .name = "_DYNAMIC", |
| 90 | .linkage = .weak, | ||
| 91 | .visibility = .hidden, | ||
| 92 | }); | ||
| 90 | } | 93 | } |
| 91 | 94 | ||
| 92 | pub fn linkmap_iterator(phdrs: []elf.Phdr) error{InvalidExe}!LinkMap.Iterator { | 95 | pub fn linkmap_iterator(phdrs: []const elf.Phdr) error{InvalidExe}!LinkMap.Iterator { |
| 93 | _ = phdrs; | 96 | _ = phdrs; |
| 94 | const _DYNAMIC = get_DYNAMIC() orelse { | 97 | const _DYNAMIC = get_DYNAMIC() orelse { |
| 95 | // No PT_DYNAMIC means this is either a statically-linked program or a | 98 | // No PT_DYNAMIC means this is either a statically-linked program or a |
lib/std/pie.zig+174-169| ... | @@ -39,167 +39,175 @@ const R_RELATIVE = switch (builtin.cpu.arch) { | ... | @@ -39,167 +39,175 @@ const R_RELATIVE = switch (builtin.cpu.arch) { |
| 39 | // Obtain a pointer to the _DYNAMIC array. | 39 | // Obtain a pointer to the _DYNAMIC array. |
| 40 | // We have to compute its address as a PC-relative quantity not to require a | 40 | // We have to compute its address as a PC-relative quantity not to require a |
| 41 | // relocation that, at this point, is not yet applied. | 41 | // relocation that, at this point, is not yet applied. |
| 42 | inline fn getDynamicSymbol() [*]elf.Dyn { | 42 | inline fn getDynamicSymbol() [*]const elf.Dyn { |
| 43 | return switch (builtin.cpu.arch) { | 43 | return switch (builtin.zig_backend) { |
| 44 | .x86 => asm volatile ( | 44 | else => switch (builtin.cpu.arch) { |
| 45 | \\ .weak _DYNAMIC | 45 | .x86 => asm volatile ( |
| 46 | \\ .hidden _DYNAMIC | 46 | \\ .weak _DYNAMIC |
| 47 | \\ call 1f | 47 | \\ .hidden _DYNAMIC |
| 48 | \\ 1: pop %[ret] | 48 | \\ call 1f |
| 49 | \\ lea _DYNAMIC-1b(%[ret]), %[ret] | 49 | \\ 1: pop %[ret] |
| 50 | : [ret] "=r" (-> [*]elf.Dyn), | 50 | \\ lea _DYNAMIC-1b(%[ret]), %[ret] |
| 51 | ), | 51 | : [ret] "=r" (-> [*]const elf.Dyn), |
| 52 | .x86_64 => asm volatile ( | 52 | ), |
| 53 | \\ .weak _DYNAMIC | 53 | .x86_64 => asm volatile ( |
| 54 | \\ .hidden _DYNAMIC | 54 | \\ .weak _DYNAMIC |
| 55 | \\ lea _DYNAMIC(%%rip), %[ret] | 55 | \\ .hidden _DYNAMIC |
| 56 | : [ret] "=r" (-> [*]elf.Dyn), | 56 | \\ lea _DYNAMIC(%%rip), %[ret] |
| 57 | ), | 57 | : [ret] "=r" (-> [*]const elf.Dyn), |
| 58 | .arc => asm volatile ( | 58 | ), |
| 59 | \\ .weak _DYNAMIC | 59 | .arc => asm volatile ( |
| 60 | \\ .hidden _DYNAMIC | 60 | \\ .weak _DYNAMIC |
| 61 | \\ add %[ret], pcl, _DYNAMIC@pcl | 61 | \\ .hidden _DYNAMIC |
| 62 | : [ret] "=r" (-> [*]elf.Dyn), | 62 | \\ add %[ret], pcl, _DYNAMIC@pcl |
| 63 | ), | 63 | : [ret] "=r" (-> [*]const elf.Dyn), |
| 64 | // Work around the limited offset range of `ldr` | 64 | ), |
| 65 | .arm, .armeb, .thumb, .thumbeb => asm volatile ( | 65 | // Work around the limited offset range of `ldr` |
| 66 | \\ .weak _DYNAMIC | 66 | .arm, .armeb, .thumb, .thumbeb => asm volatile ( |
| 67 | \\ .hidden _DYNAMIC | 67 | \\ .weak _DYNAMIC |
| 68 | \\ ldr %[ret], 1f | 68 | \\ .hidden _DYNAMIC |
| 69 | \\ add %[ret], pc | 69 | \\ ldr %[ret], 1f |
| 70 | \\ b 2f | 70 | \\ add %[ret], pc |
| 71 | \\ 1: .word _DYNAMIC-1b | 71 | \\ b 2f |
| 72 | \\ 2: | 72 | \\ 1: .word _DYNAMIC-1b |
| 73 | : [ret] "=r" (-> [*]elf.Dyn), | 73 | \\ 2: |
| 74 | ), | 74 | : [ret] "=r" (-> [*]const elf.Dyn), |
| 75 | // A simple `adr` is not enough as it has a limited offset range | 75 | ), |
| 76 | .aarch64, .aarch64_be => asm volatile ( | 76 | // A simple `adr` is not enough as it has a limited offset range |
| 77 | \\ .weak _DYNAMIC | 77 | .aarch64, .aarch64_be => asm volatile ( |
| 78 | \\ .hidden _DYNAMIC | 78 | \\ .weak _DYNAMIC |
| 79 | \\ adrp %[ret], _DYNAMIC | 79 | \\ .hidden _DYNAMIC |
| 80 | \\ add %[ret], %[ret], #:lo12:_DYNAMIC | 80 | \\ adrp %[ret], _DYNAMIC |
| 81 | : [ret] "=r" (-> [*]elf.Dyn), | 81 | \\ add %[ret], %[ret], #:lo12:_DYNAMIC |
| 82 | ), | 82 | : [ret] "=r" (-> [*]const elf.Dyn), |
| 83 | // The CSKY ABI requires the gb register to point to the GOT. Additionally, the first | 83 | ), |
| 84 | // entry in the GOT is defined to hold the address of _DYNAMIC. | 84 | // The CSKY ABI requires the gb register to point to the GOT. Additionally, the first |
| 85 | .csky => asm volatile ( | 85 | // entry in the GOT is defined to hold the address of _DYNAMIC. |
| 86 | \\ mov %[ret], gb | 86 | .csky => asm volatile ( |
| 87 | \\ ldw %[ret], %[ret] | 87 | \\ mov %[ret], gb |
| 88 | : [ret] "=r" (-> [*]elf.Dyn), | 88 | \\ ldw %[ret], %[ret] |
| 89 | ), | 89 | : [ret] "=r" (-> [*]const elf.Dyn), |
| 90 | .hexagon => asm volatile ( | 90 | ), |
| 91 | \\ .weak _DYNAMIC | 91 | .hexagon => asm volatile ( |
| 92 | \\ .hidden _DYNAMIC | 92 | \\ .weak _DYNAMIC |
| 93 | \\ jump 1f | 93 | \\ .hidden _DYNAMIC |
| 94 | \\ .word _DYNAMIC - . | 94 | \\ jump 1f |
| 95 | \\ 1: | 95 | \\ .word _DYNAMIC - . |
| 96 | \\ r1 = pc | 96 | \\ 1: |
| 97 | \\ r1 = add(r1, #-4) | 97 | \\ r1 = pc |
| 98 | \\ %[ret] = memw(r1) | 98 | \\ r1 = add(r1, #-4) |
| 99 | \\ %[ret] = add(r1, %[ret]) | 99 | \\ %[ret] = memw(r1) |
| 100 | : [ret] "=r" (-> [*]elf.Dyn), | 100 | \\ %[ret] = add(r1, %[ret]) |
| 101 | : | 101 | : [ret] "=r" (-> [*]const elf.Dyn), |
| 102 | : "r1" | 102 | : |
| 103 | ), | 103 | : "r1" |
| 104 | .loongarch32, .loongarch64 => asm volatile ( | 104 | ), |
| 105 | \\ .weak _DYNAMIC | 105 | .loongarch32, .loongarch64 => asm volatile ( |
| 106 | \\ .hidden _DYNAMIC | 106 | \\ .weak _DYNAMIC |
| 107 | \\ la.local %[ret], _DYNAMIC | 107 | \\ .hidden _DYNAMIC |
| 108 | : [ret] "=r" (-> [*]elf.Dyn), | 108 | \\ la.local %[ret], _DYNAMIC |
| 109 | ), | 109 | : [ret] "=r" (-> [*]const elf.Dyn), |
| 110 | // Note that the - 8 is needed because pc in the second lea instruction points into the | 110 | ), |
| 111 | // middle of that instruction. (The first lea is 6 bytes, the second is 4 bytes.) | 111 | // Note that the - 8 is needed because pc in the second lea instruction points into the |
| 112 | .m68k => asm volatile ( | 112 | // middle of that instruction. (The first lea is 6 bytes, the second is 4 bytes.) |
| 113 | \\ .weak _DYNAMIC | 113 | .m68k => asm volatile ( |
| 114 | \\ .hidden _DYNAMIC | 114 | \\ .weak _DYNAMIC |
| 115 | \\ lea _DYNAMIC - . - 8, %[ret] | 115 | \\ .hidden _DYNAMIC |
| 116 | \\ lea (%[ret], %%pc), %[ret] | 116 | \\ lea _DYNAMIC - . - 8, %[ret] |
| 117 | : [ret] "=r" (-> [*]elf.Dyn), | 117 | \\ lea (%[ret], %%pc), %[ret] |
| 118 | ), | 118 | : [ret] "=r" (-> [*]const elf.Dyn), |
| 119 | .mips, .mipsel => asm volatile ( | 119 | ), |
| 120 | \\ .weak _DYNAMIC | 120 | .mips, .mipsel => asm volatile ( |
| 121 | \\ .hidden _DYNAMIC | 121 | \\ .weak _DYNAMIC |
| 122 | \\ bal 1f | 122 | \\ .hidden _DYNAMIC |
| 123 | \\ .gpword _DYNAMIC | 123 | \\ bal 1f |
| 124 | \\ 1: | 124 | \\ .gpword _DYNAMIC |
| 125 | \\ lw %[ret], 0($ra) | 125 | \\ 1: |
| 126 | \\ addu %[ret], %[ret], $gp | 126 | \\ lw %[ret], 0($ra) |
| 127 | : [ret] "=r" (-> [*]elf.Dyn), | 127 | \\ addu %[ret], %[ret], $gp |
| 128 | : | 128 | : [ret] "=r" (-> [*]const elf.Dyn), |
| 129 | : "lr" | 129 | : |
| 130 | ), | 130 | : "lr" |
| 131 | .mips64, .mips64el => asm volatile ( | 131 | ), |
| 132 | \\ .weak _DYNAMIC | 132 | .mips64, .mips64el => asm volatile ( |
| 133 | \\ .hidden _DYNAMIC | 133 | \\ .weak _DYNAMIC |
| 134 | \\ .balign 8 | 134 | \\ .hidden _DYNAMIC |
| 135 | \\ bal 1f | 135 | \\ .balign 8 |
| 136 | \\ .gpdword _DYNAMIC | 136 | \\ bal 1f |
| 137 | \\ 1: | 137 | \\ .gpdword _DYNAMIC |
| 138 | \\ ld %[ret], 0($ra) | 138 | \\ 1: |
| 139 | \\ daddu %[ret], %[ret], $gp | 139 | \\ ld %[ret], 0($ra) |
| 140 | : [ret] "=r" (-> [*]elf.Dyn), | 140 | \\ daddu %[ret], %[ret], $gp |
| 141 | : | 141 | : [ret] "=r" (-> [*]const elf.Dyn), |
| 142 | : "lr" | 142 | : |
| 143 | ), | 143 | : "lr" |
| 144 | .powerpc, .powerpcle => asm volatile ( | 144 | ), |
| 145 | \\ .weak _DYNAMIC | 145 | .powerpc, .powerpcle => asm volatile ( |
| 146 | \\ .hidden _DYNAMIC | 146 | \\ .weak _DYNAMIC |
| 147 | \\ bl 1f | 147 | \\ .hidden _DYNAMIC |
| 148 | \\ .long _DYNAMIC - . | 148 | \\ bl 1f |
| 149 | \\ 1: | 149 | \\ .long _DYNAMIC - . |
| 150 | \\ mflr %[ret] | 150 | \\ 1: |
| 151 | \\ lwz 4, 0(%[ret]) | 151 | \\ mflr %[ret] |
| 152 | \\ add %[ret], 4, %[ret] | 152 | \\ lwz 4, 0(%[ret]) |
| 153 | : [ret] "=r" (-> [*]elf.Dyn), | 153 | \\ add %[ret], 4, %[ret] |
| 154 | : | 154 | : [ret] "=r" (-> [*]const elf.Dyn), |
| 155 | : "lr", "r4" | 155 | : |
| 156 | ), | 156 | : "lr", "r4" |
| 157 | .powerpc64, .powerpc64le => asm volatile ( | 157 | ), |
| 158 | \\ .weak _DYNAMIC | 158 | .powerpc64, .powerpc64le => asm volatile ( |
| 159 | \\ .hidden _DYNAMIC | 159 | \\ .weak _DYNAMIC |
| 160 | \\ bl 1f | 160 | \\ .hidden _DYNAMIC |
| 161 | \\ .quad _DYNAMIC - . | 161 | \\ bl 1f |
| 162 | \\ 1: | 162 | \\ .quad _DYNAMIC - . |
| 163 | \\ mflr %[ret] | 163 | \\ 1: |
| 164 | \\ ld 4, 0(%[ret]) | 164 | \\ mflr %[ret] |
| 165 | \\ add %[ret], 4, %[ret] | 165 | \\ ld 4, 0(%[ret]) |
| 166 | : [ret] "=r" (-> [*]elf.Dyn), | 166 | \\ add %[ret], 4, %[ret] |
| 167 | : | 167 | : [ret] "=r" (-> [*]const elf.Dyn), |
| 168 | : "lr", "r4" | 168 | : |
| 169 | ), | 169 | : "lr", "r4" |
| 170 | .riscv32, .riscv64 => asm volatile ( | 170 | ), |
| 171 | \\ .weak _DYNAMIC | 171 | .riscv32, .riscv64 => asm volatile ( |
| 172 | \\ .hidden _DYNAMIC | 172 | \\ .weak _DYNAMIC |
| 173 | \\ lla %[ret], _DYNAMIC | 173 | \\ .hidden _DYNAMIC |
| 174 | : [ret] "=r" (-> [*]elf.Dyn), | 174 | \\ lla %[ret], _DYNAMIC |
| 175 | ), | 175 | : [ret] "=r" (-> [*]const elf.Dyn), |
| 176 | .s390x => asm volatile ( | 176 | ), |
| 177 | \\ .weak _DYNAMIC | 177 | .s390x => asm volatile ( |
| 178 | \\ .hidden _DYNAMIC | 178 | \\ .weak _DYNAMIC |
| 179 | \\ larl %[ret], 1f | 179 | \\ .hidden _DYNAMIC |
| 180 | \\ ag %[ret], 0(%[ret]) | 180 | \\ larl %[ret], 1f |
| 181 | \\ jg 2f | 181 | \\ ag %[ret], 0(%[ret]) |
| 182 | \\ 1: .quad _DYNAMIC - . | 182 | \\ jg 2f |
| 183 | \\ 2: | 183 | \\ 1: .quad _DYNAMIC - . |
| 184 | : [ret] "=r" (-> [*]elf.Dyn), | 184 | \\ 2: |
| 185 | ), | 185 | : [ret] "=r" (-> [*]const elf.Dyn), |
| 186 | // The compiler does not necessarily have any obligation to load the `l7` register (pointing | 186 | ), |
| 187 | // to the GOT), so do it ourselves just in case. | 187 | // The compiler does not necessarily have any obligation to load the `l7` register (pointing |
| 188 | .sparc, .sparc64 => asm volatile ( | 188 | // to the GOT), so do it ourselves just in case. |
| 189 | \\ sethi %%hi(_GLOBAL_OFFSET_TABLE_ - 4), %%l7 | 189 | .sparc, .sparc64 => asm volatile ( |
| 190 | \\ call 1f | 190 | \\ sethi %%hi(_GLOBAL_OFFSET_TABLE_ - 4), %%l7 |
| 191 | \\ add %%l7, %%lo(_GLOBAL_OFFSET_TABLE_ + 4), %%l7 | 191 | \\ call 1f |
| 192 | \\ 1: | 192 | \\ add %%l7, %%lo(_GLOBAL_OFFSET_TABLE_ + 4), %%l7 |
| 193 | \\ add %%l7, %%o7, %[ret] | 193 | \\ 1: |
| 194 | : [ret] "=r" (-> [*]elf.Dyn), | 194 | \\ add %%l7, %%o7, %[ret] |
| 195 | ), | 195 | : [ret] "=r" (-> [*]const elf.Dyn), |
| 196 | else => { | 196 | ), |
| 197 | @compileError("PIE startup is not yet supported for this target!"); | 197 | else => { |
| 198 | @compileError("PIE startup is not yet supported for this target!"); | ||
| 199 | }, | ||
| 198 | }, | 200 | }, |
| 201 | .stage2_x86_64 => @extern([*]const elf.Dyn, .{ | ||
| 202 | .name = "_DYNAMIC", | ||
| 203 | .linkage = .weak, | ||
| 204 | .visibility = .hidden, | ||
| 205 | .relocation = .pcrel, | ||
| 206 | }).?, | ||
| 199 | }; | 207 | }; |
| 200 | } | 208 | } |
| 201 | 209 | ||
| 202 | pub fn relocate(phdrs: []elf.Phdr) void { | 210 | pub fn relocate(phdrs: []const elf.Phdr) void { |
| 203 | @setRuntimeSafety(false); | 211 | @setRuntimeSafety(false); |
| 204 | @disableInstrumentation(); | 212 | @disableInstrumentation(); |
| 205 | 213 | ||
| ... | @@ -256,10 +264,9 @@ pub fn relocate(phdrs: []elf.Phdr) void { | ... | @@ -256,10 +264,9 @@ pub fn relocate(phdrs: []elf.Phdr) void { |
| 256 | 264 | ||
| 257 | const rel = sorted_dynv[elf.DT_REL]; | 265 | const rel = sorted_dynv[elf.DT_REL]; |
| 258 | if (rel != 0) { | 266 | if (rel != 0) { |
| 259 | const rels = @call(.always_inline, std.mem.bytesAsSlice, .{ | 267 | const rels: []const elf.Rel = @alignCast(@ptrCast( |
| 260 | elf.Rel, | 268 | @as([*]align(@alignOf(elf.Rel)) const u8, @ptrFromInt(base_addr + rel))[0..sorted_dynv[elf.DT_RELSZ]], |
| 261 | @as([*]u8, @ptrFromInt(base_addr + rel))[0..sorted_dynv[elf.DT_RELSZ]], | 269 | )); |
| 262 | }); | ||
| 263 | for (rels) |r| { | 270 | for (rels) |r| { |
| 264 | if (r.r_type() != R_RELATIVE) continue; | 271 | if (r.r_type() != R_RELATIVE) continue; |
| 265 | @as(*usize, @ptrFromInt(base_addr + r.r_offset)).* += base_addr; | 272 | @as(*usize, @ptrFromInt(base_addr + r.r_offset)).* += base_addr; |
| ... | @@ -268,10 +275,9 @@ pub fn relocate(phdrs: []elf.Phdr) void { | ... | @@ -268,10 +275,9 @@ pub fn relocate(phdrs: []elf.Phdr) void { |
| 268 | 275 | ||
| 269 | const rela = sorted_dynv[elf.DT_RELA]; | 276 | const rela = sorted_dynv[elf.DT_RELA]; |
| 270 | if (rela != 0) { | 277 | if (rela != 0) { |
| 271 | const relas = @call(.always_inline, std.mem.bytesAsSlice, .{ | 278 | const relas: []const elf.Rela = @alignCast(@ptrCast( |
| 272 | elf.Rela, | 279 | @as([*]align(@alignOf(elf.Rela)) const u8, @ptrFromInt(base_addr + rela))[0..sorted_dynv[elf.DT_RELASZ]], |
| 273 | @as([*]u8, @ptrFromInt(base_addr + rela))[0..sorted_dynv[elf.DT_RELASZ]], | 280 | )); |
| 274 | }); | ||
| 275 | for (relas) |r| { | 281 | for (relas) |r| { |
| 276 | if (r.r_type() != R_RELATIVE) continue; | 282 | if (r.r_type() != R_RELATIVE) continue; |
| 277 | @as(*usize, @ptrFromInt(base_addr + r.r_offset)).* = base_addr + @as(usize, @bitCast(r.r_addend)); | 283 | @as(*usize, @ptrFromInt(base_addr + r.r_offset)).* = base_addr + @as(usize, @bitCast(r.r_addend)); |
| ... | @@ -280,10 +286,9 @@ pub fn relocate(phdrs: []elf.Phdr) void { | ... | @@ -280,10 +286,9 @@ pub fn relocate(phdrs: []elf.Phdr) void { |
| 280 | 286 | ||
| 281 | const relr = sorted_dynv[elf.DT_RELR]; | 287 | const relr = sorted_dynv[elf.DT_RELR]; |
| 282 | if (relr != 0) { | 288 | if (relr != 0) { |
| 283 | const relrs = @call(.always_inline, std.mem.bytesAsSlice, .{ | 289 | const relrs: []const elf.Relr = @ptrCast( |
| 284 | elf.Relr, | 290 | @as([*]align(@alignOf(elf.Relr)) const u8, @ptrFromInt(base_addr + relr))[0..sorted_dynv[elf.DT_RELRSZ]], |
| 285 | @as([*]u8, @ptrFromInt(base_addr + relr))[0..sorted_dynv[elf.DT_RELRSZ]], | 291 | ); |
| 286 | }); | ||
| 287 | var current: [*]usize = undefined; | 292 | var current: [*]usize = undefined; |
| 288 | for (relrs) |r| { | 293 | for (relrs) |r| { |
| 289 | if ((r & 1) == 0) { | 294 | if ((r & 1) == 0) { |
lib/std/start.zig+6-6| ... | @@ -163,7 +163,7 @@ fn exit2(code: usize) noreturn { | ... | @@ -163,7 +163,7 @@ fn exit2(code: usize) noreturn { |
| 163 | // exits(0) | 163 | // exits(0) |
| 164 | .plan9 => std.os.plan9.exits(null), | 164 | .plan9 => std.os.plan9.exits(null), |
| 165 | .windows => { | 165 | .windows => { |
| 166 | std.os.windows.ntdll.RtlExitUserProcess(@as(u32, @truncate(code))); | 166 | std.os.windows.ntdll.RtlExitUserProcess(@truncate(code)); |
| 167 | }, | 167 | }, |
| 168 | else => @compileError("TODO"), | 168 | else => @compileError("TODO"), |
| 169 | } | 169 | } |
| ... | @@ -511,7 +511,7 @@ fn posixCallMainAndExit(argc_argv_ptr: [*]usize) callconv(.c) noreturn { | ... | @@ -511,7 +511,7 @@ fn posixCallMainAndExit(argc_argv_ptr: [*]usize) callconv(.c) noreturn { |
| 511 | // Code coverage instrumentation might try to use thread local variables. | 511 | // Code coverage instrumentation might try to use thread local variables. |
| 512 | @disableInstrumentation(); | 512 | @disableInstrumentation(); |
| 513 | const argc = argc_argv_ptr[0]; | 513 | const argc = argc_argv_ptr[0]; |
| 514 | const argv = @as([*][*:0]u8, @ptrCast(argc_argv_ptr + 1)); | 514 | const argv: [*][*:0]u8 = @ptrCast(argc_argv_ptr + 1); |
| 515 | 515 | ||
| 516 | const envp_optional: [*:null]?[*:0]u8 = @ptrCast(@alignCast(argv + argc + 1)); | 516 | const envp_optional: [*:null]?[*:0]u8 = @ptrCast(@alignCast(argv + argc + 1)); |
| 517 | var envp_count: usize = 0; | 517 | var envp_count: usize = 0; |
| ... | @@ -573,11 +573,11 @@ fn posixCallMainAndExit(argc_argv_ptr: [*]usize) callconv(.c) noreturn { | ... | @@ -573,11 +573,11 @@ fn posixCallMainAndExit(argc_argv_ptr: [*]usize) callconv(.c) noreturn { |
| 573 | expandStackSize(phdrs); | 573 | expandStackSize(phdrs); |
| 574 | } | 574 | } |
| 575 | 575 | ||
| 576 | const opt_init_array_start = @extern([*]*const fn () callconv(.c) void, .{ | 576 | const opt_init_array_start = @extern([*]const *const fn () callconv(.c) void, .{ |
| 577 | .name = "__init_array_start", | 577 | .name = "__init_array_start", |
| 578 | .linkage = .weak, | 578 | .linkage = .weak, |
| 579 | }); | 579 | }); |
| 580 | const opt_init_array_end = @extern([*]*const fn () callconv(.c) void, .{ | 580 | const opt_init_array_end = @extern([*]const *const fn () callconv(.c) void, .{ |
| 581 | .name = "__init_array_end", | 581 | .name = "__init_array_end", |
| 582 | .linkage = .weak, | 582 | .linkage = .weak, |
| 583 | }); | 583 | }); |
| ... | @@ -651,7 +651,7 @@ fn main(c_argc: c_int, c_argv: [*][*:0]c_char, c_envp: [*:null]?[*:0]c_char) cal | ... | @@ -651,7 +651,7 @@ fn main(c_argc: c_int, c_argv: [*][*:0]c_char, c_envp: [*:null]?[*:0]c_char) cal |
| 651 | } | 651 | } |
| 652 | 652 | ||
| 653 | fn mainWithoutEnv(c_argc: c_int, c_argv: [*][*:0]c_char) callconv(.c) c_int { | 653 | fn mainWithoutEnv(c_argc: c_int, c_argv: [*][*:0]c_char) callconv(.c) c_int { |
| 654 | std.os.argv = @as([*][*:0]u8, @ptrCast(c_argv))[0..@as(usize, @intCast(c_argc))]; | 654 | std.os.argv = @as([*][*:0]u8, @ptrCast(c_argv))[0..@intCast(c_argc)]; |
| 655 | return callMain(); | 655 | return callMain(); |
| 656 | } | 656 | } |
| 657 | 657 | ||
| ... | @@ -701,7 +701,7 @@ pub inline fn callMain() u8 { | ... | @@ -701,7 +701,7 @@ pub inline fn callMain() u8 { |
| 701 | pub fn call_wWinMain() std.os.windows.INT { | 701 | pub fn call_wWinMain() std.os.windows.INT { |
| 702 | const peb = std.os.windows.peb(); | 702 | const peb = std.os.windows.peb(); |
| 703 | const MAIN_HINSTANCE = @typeInfo(@TypeOf(root.wWinMain)).@"fn".params[0].type.?; | 703 | const MAIN_HINSTANCE = @typeInfo(@TypeOf(root.wWinMain)).@"fn".params[0].type.?; |
| 704 | const hInstance = @as(MAIN_HINSTANCE, @ptrCast(peb.ImageBaseAddress)); | 704 | const hInstance: MAIN_HINSTANCE = @ptrCast(peb.ImageBaseAddress); |
| 705 | const lpCmdLine: [*:0]u16 = @ptrCast(peb.ProcessParameters.CommandLine.Buffer); | 705 | const lpCmdLine: [*:0]u16 = @ptrCast(peb.ProcessParameters.CommandLine.Buffer); |
| 706 | 706 | ||
| 707 | // There are various types used for the 'show window' variable through the Win32 APIs: | 707 | // There are various types used for the 'show window' variable through the Win32 APIs: |
lib/std/zig/llvm/Builder.zig+12| ... | @@ -1823,6 +1823,14 @@ pub const Visibility = enum(u2) { | ... | @@ -1823,6 +1823,14 @@ pub const Visibility = enum(u2) { |
| 1823 | hidden = 1, | 1823 | hidden = 1, |
| 1824 | protected = 2, | 1824 | protected = 2, |
| 1825 | 1825 | ||
| 1826 | pub fn fromSymbolVisibility(sv: std.builtin.SymbolVisibility) Visibility { | ||
| 1827 | return switch (sv) { | ||
| 1828 | .default => .default, | ||
| 1829 | .hidden => .hidden, | ||
| 1830 | .protected => .protected, | ||
| 1831 | }; | ||
| 1832 | } | ||
| 1833 | |||
| 1826 | pub fn format( | 1834 | pub fn format( |
| 1827 | self: Visibility, | 1835 | self: Visibility, |
| 1828 | comptime _: []const u8, | 1836 | comptime _: []const u8, |
| ... | @@ -2555,6 +2563,10 @@ pub const Variable = struct { | ... | @@ -2555,6 +2563,10 @@ pub const Variable = struct { |
| 2555 | return self.ptrConst(builder).global.setLinkage(linkage, builder); | 2563 | return self.ptrConst(builder).global.setLinkage(linkage, builder); |
| 2556 | } | 2564 | } |
| 2557 | 2565 | ||
| 2566 | pub fn setVisibility(self: Index, visibility: Visibility, builder: *Builder) void { | ||
| 2567 | return self.ptrConst(builder).global.setVisibility(visibility, builder); | ||
| 2568 | } | ||
| 2569 | |||
| 2558 | pub fn setDllStorageClass(self: Index, class: DllStorageClass, builder: *Builder) void { | 2570 | pub fn setDllStorageClass(self: Index, class: DllStorageClass, builder: *Builder) void { |
| 2559 | return self.ptrConst(builder).global.setDllStorageClass(class, builder); | 2571 | return self.ptrConst(builder).global.setDllStorageClass(class, builder); |
| 2560 | } | 2572 | } |
lib/zig.h+9| ... | @@ -272,6 +272,15 @@ | ... | @@ -272,6 +272,15 @@ |
| 272 | #define zig_linksection_fn zig_linksection | 272 | #define zig_linksection_fn zig_linksection |
| 273 | #endif | 273 | #endif |
| 274 | 274 | ||
| 275 | #if zig_has_attribute(visibility) | ||
| 276 | #define zig_visibility(name) __attribute__((visibility(#name))) | ||
| 277 | #else | ||
| 278 | #define zig_visibility(name) zig_visibility_##name | ||
| 279 | #define zig_visibility_default | ||
| 280 | #define zig_visibility_hidden zig_visibility_hidden_unavailable | ||
| 281 | #define zig_visibility_protected zig_visibility_protected_unavailable | ||
| 282 | #endif | ||
| 283 | |||
| 275 | #if zig_has_builtin(unreachable) || defined(zig_gcc) || defined(zig_tinyc) | 284 | #if zig_has_builtin(unreachable) || defined(zig_gcc) || defined(zig_tinyc) |
| 276 | #define zig_unreachable() __builtin_unreachable() | 285 | #define zig_unreachable() __builtin_unreachable() |
| 277 | #elif defined(zig_msvc) | 286 | #elif defined(zig_msvc) |
src/Air.zig+10-4| ... | @@ -13,6 +13,7 @@ const InternPool = @import("InternPool.zig"); | ... | @@ -13,6 +13,7 @@ const InternPool = @import("InternPool.zig"); |
| 13 | const Type = @import("Type.zig"); | 13 | const Type = @import("Type.zig"); |
| 14 | const Value = @import("Value.zig"); | 14 | const Value = @import("Value.zig"); |
| 15 | const Zcu = @import("Zcu.zig"); | 15 | const Zcu = @import("Zcu.zig"); |
| 16 | const print = @import("Air/print.zig"); | ||
| 16 | const types_resolved = @import("Air/types_resolved.zig"); | 17 | const types_resolved = @import("Air/types_resolved.zig"); |
| 17 | 18 | ||
| 18 | pub const Legalize = @import("Air/Legalize.zig"); | 19 | pub const Legalize = @import("Air/Legalize.zig"); |
| ... | @@ -863,16 +864,17 @@ pub const Inst = struct { | ... | @@ -863,16 +864,17 @@ pub const Inst = struct { |
| 863 | /// Uses the `vector_store_elem` field. | 864 | /// Uses the `vector_store_elem` field. |
| 864 | vector_store_elem, | 865 | vector_store_elem, |
| 865 | 866 | ||
| 866 | /// Compute a pointer to a threadlocal or dllimport `Nav`, meaning one of: | 867 | /// Compute a pointer to a `Nav` at runtime, always one of: |
| 867 | /// | 868 | /// |
| 868 | /// * `threadlocal var` | 869 | /// * `threadlocal var` |
| 869 | /// * `extern threadlocal var` (or corresponding `@extern`) | 870 | /// * `extern threadlocal var` (or corresponding `@extern`) |
| 870 | /// * `@extern` with `.is_dll_import = true` | 871 | /// * `@extern` with `.is_dll_import = true` |
| 872 | /// * `@extern` with `.relocation = .pcrel` | ||
| 871 | /// | 873 | /// |
| 872 | /// Such pointers are runtime values, so cannot be represented with an InternPool index. | 874 | /// Such pointers are runtime values, so cannot be represented with an InternPool index. |
| 873 | /// | 875 | /// |
| 874 | /// Uses the `ty_nav` field. | 876 | /// Uses the `ty_nav` field. |
| 875 | tlv_dllimport_ptr, | 877 | runtime_nav_ptr, |
| 876 | 878 | ||
| 877 | /// Implements @cVaArg builtin. | 879 | /// Implements @cVaArg builtin. |
| 878 | /// Uses the `ty_op` field. | 880 | /// Uses the `ty_op` field. |
| ... | @@ -1708,7 +1710,7 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool) | ... | @@ -1708,7 +1710,7 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool) |
| 1708 | return .fromInterned(ip.indexToKey(err_union_ty.ip_index).error_union_type.payload_type); | 1710 | return .fromInterned(ip.indexToKey(err_union_ty.ip_index).error_union_type.payload_type); |
| 1709 | }, | 1711 | }, |
| 1710 | 1712 | ||
| 1711 | .tlv_dllimport_ptr => return .fromInterned(datas[@intFromEnum(inst)].ty_nav.ty), | 1713 | .runtime_nav_ptr => return .fromInterned(datas[@intFromEnum(inst)].ty_nav.ty), |
| 1712 | 1714 | ||
| 1713 | .work_item_id, | 1715 | .work_item_id, |
| 1714 | .work_group_size, | 1716 | .work_group_size, |
| ... | @@ -1983,7 +1985,7 @@ pub fn mustLower(air: Air, inst: Air.Inst.Index, ip: *const InternPool) bool { | ... | @@ -1983,7 +1985,7 @@ pub fn mustLower(air: Air, inst: Air.Inst.Index, ip: *const InternPool) bool { |
| 1983 | .err_return_trace, | 1985 | .err_return_trace, |
| 1984 | .addrspace_cast, | 1986 | .addrspace_cast, |
| 1985 | .save_err_return_trace_index, | 1987 | .save_err_return_trace_index, |
| 1986 | .tlv_dllimport_ptr, | 1988 | .runtime_nav_ptr, |
| 1987 | .work_item_id, | 1989 | .work_item_id, |
| 1988 | .work_group_size, | 1990 | .work_group_size, |
| 1989 | .work_group_id, | 1991 | .work_group_id, |
| ... | @@ -2141,6 +2143,10 @@ pub const typesFullyResolved = types_resolved.typesFullyResolved; | ... | @@ -2141,6 +2143,10 @@ pub const typesFullyResolved = types_resolved.typesFullyResolved; |
| 2141 | pub const typeFullyResolved = types_resolved.checkType; | 2143 | pub const typeFullyResolved = types_resolved.checkType; |
| 2142 | pub const valFullyResolved = types_resolved.checkVal; | 2144 | pub const valFullyResolved = types_resolved.checkVal; |
| 2143 | pub const legalize = Legalize.legalize; | 2145 | pub const legalize = Legalize.legalize; |
| 2146 | pub const write = print.write; | ||
| 2147 | pub const writeInst = print.writeInst; | ||
| 2148 | pub const dump = print.dump; | ||
| 2149 | pub const dumpInst = print.dumpInst; | ||
| 2144 | 2150 | ||
| 2145 | pub const CoveragePoint = enum(u1) { | 2151 | pub const CoveragePoint = enum(u1) { |
| 2146 | /// Indicates the block is not a place of interest corresponding to | 2152 | /// Indicates the block is not a place of interest corresponding to |
src/Air/Legalize.zig+1-1| ... | @@ -622,7 +622,7 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void { | ... | @@ -622,7 +622,7 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void { |
| 622 | .addrspace_cast, | 622 | .addrspace_cast, |
| 623 | .save_err_return_trace_index, | 623 | .save_err_return_trace_index, |
| 624 | .vector_store_elem, | 624 | .vector_store_elem, |
| 625 | .tlv_dllimport_ptr, | 625 | .runtime_nav_ptr, |
| 626 | .c_va_arg, | 626 | .c_va_arg, |
| 627 | .c_va_copy, | 627 | .c_va_copy, |
| 628 | .c_va_end, | 628 | .c_va_end, |
src/Air/Liveness.zig+2-2| ... | @@ -339,7 +339,7 @@ pub fn categorizeOperand( | ... | @@ -339,7 +339,7 @@ pub fn categorizeOperand( |
| 339 | .wasm_memory_size, | 339 | .wasm_memory_size, |
| 340 | .err_return_trace, | 340 | .err_return_trace, |
| 341 | .save_err_return_trace_index, | 341 | .save_err_return_trace_index, |
| 342 | .tlv_dllimport_ptr, | 342 | .runtime_nav_ptr, |
| 343 | .c_va_start, | 343 | .c_va_start, |
| 344 | .work_item_id, | 344 | .work_item_id, |
| 345 | .work_group_size, | 345 | .work_group_size, |
| ... | @@ -972,7 +972,7 @@ fn analyzeInst( | ... | @@ -972,7 +972,7 @@ fn analyzeInst( |
| 972 | .wasm_memory_size, | 972 | .wasm_memory_size, |
| 973 | .err_return_trace, | 973 | .err_return_trace, |
| 974 | .save_err_return_trace_index, | 974 | .save_err_return_trace_index, |
| 975 | .tlv_dllimport_ptr, | 975 | .runtime_nav_ptr, |
| 976 | .c_va_start, | 976 | .c_va_start, |
| 977 | .work_item_id, | 977 | .work_item_id, |
| 978 | .work_group_size, | 978 | .work_group_size, |
src/Air/Liveness/Verify.zig+1-1| ... | @@ -63,7 +63,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void { | ... | @@ -63,7 +63,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void { |
| 63 | .wasm_memory_size, | 63 | .wasm_memory_size, |
| 64 | .err_return_trace, | 64 | .err_return_trace, |
| 65 | .save_err_return_trace_index, | 65 | .save_err_return_trace_index, |
| 66 | .tlv_dllimport_ptr, | 66 | .runtime_nav_ptr, |
| 67 | .c_va_start, | 67 | .c_va_start, |
| 68 | .work_item_id, | 68 | .work_item_id, |
| 69 | .work_group_size, | 69 | .work_group_size, |
src/Air/print.zig created+1041| ... | @@ -0,0 +1,1041 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const Allocator = std.mem.Allocator; | ||
| 3 | const fmtIntSizeBin = std.fmt.fmtIntSizeBin; | ||
| 4 | |||
| 5 | const build_options = @import("build_options"); | ||
| 6 | const Zcu = @import("../Zcu.zig"); | ||
| 7 | const Value = @import("../Value.zig"); | ||
| 8 | const Type = @import("../Type.zig"); | ||
| 9 | const Air = @import("../Air.zig"); | ||
| 10 | const InternPool = @import("../InternPool.zig"); | ||
| 11 | |||
| 12 | pub fn write(air: Air, stream: anytype, pt: Zcu.PerThread, liveness: ?Air.Liveness) void { | ||
| 13 | comptime std.debug.assert(build_options.enable_debug_extensions); | ||
| 14 | const instruction_bytes = air.instructions.len * | ||
| 15 | // Here we don't use @sizeOf(Air.Inst.Data) because it would include | ||
| 16 | // the debug safety tag but we want to measure release size. | ||
| 17 | (@sizeOf(Air.Inst.Tag) + 8); | ||
| 18 | const extra_bytes = air.extra.items.len * @sizeOf(u32); | ||
| 19 | const tomb_bytes = if (liveness) |l| l.tomb_bits.len * @sizeOf(usize) else 0; | ||
| 20 | const liveness_extra_bytes = if (liveness) |l| l.extra.len * @sizeOf(u32) else 0; | ||
| 21 | const liveness_special_bytes = if (liveness) |l| l.special.count() * 8 else 0; | ||
| 22 | const total_bytes = @sizeOf(Air) + instruction_bytes + extra_bytes + | ||
| 23 | @sizeOf(Air.Liveness) + liveness_extra_bytes + | ||
| 24 | liveness_special_bytes + tomb_bytes; | ||
| 25 | |||
| 26 | // zig fmt: off | ||
| 27 | stream.print( | ||
| 28 | \\# Total AIR+Liveness bytes: {} | ||
| 29 | \\# AIR Instructions: {d} ({}) | ||
| 30 | \\# AIR Extra Data: {d} ({}) | ||
| 31 | \\# Liveness tomb_bits: {} | ||
| 32 | \\# Liveness Extra Data: {d} ({}) | ||
| 33 | \\# Liveness special table: {d} ({}) | ||
| 34 | \\ | ||
| 35 | , .{ | ||
| 36 | fmtIntSizeBin(total_bytes), | ||
| 37 | air.instructions.len, fmtIntSizeBin(instruction_bytes), | ||
| 38 | air.extra.items.len, fmtIntSizeBin(extra_bytes), | ||
| 39 | fmtIntSizeBin(tomb_bytes), | ||
| 40 | if (liveness) |l| l.extra.len else 0, fmtIntSizeBin(liveness_extra_bytes), | ||
| 41 | if (liveness) |l| l.special.count() else 0, fmtIntSizeBin(liveness_special_bytes), | ||
| 42 | }) catch return; | ||
| 43 | // zig fmt: on | ||
| 44 | |||
| 45 | var writer: Writer = .{ | ||
| 46 | .pt = pt, | ||
| 47 | .gpa = pt.zcu.gpa, | ||
| 48 | .air = air, | ||
| 49 | .liveness = liveness, | ||
| 50 | .indent = 2, | ||
| 51 | .skip_body = false, | ||
| 52 | }; | ||
| 53 | writer.writeBody(stream, air.getMainBody()) catch return; | ||
| 54 | } | ||
| 55 | |||
| 56 | pub fn writeInst( | ||
| 57 | air: Air, | ||
| 58 | stream: anytype, | ||
| 59 | inst: Air.Inst.Index, | ||
| 60 | pt: Zcu.PerThread, | ||
| 61 | liveness: ?Air.Liveness, | ||
| 62 | ) void { | ||
| 63 | comptime std.debug.assert(build_options.enable_debug_extensions); | ||
| 64 | var writer: Writer = .{ | ||
| 65 | .pt = pt, | ||
| 66 | .gpa = pt.zcu.gpa, | ||
| 67 | .air = air, | ||
| 68 | .liveness = liveness, | ||
| 69 | .indent = 2, | ||
| 70 | .skip_body = true, | ||
| 71 | }; | ||
| 72 | writer.writeInst(stream, inst) catch return; | ||
| 73 | } | ||
| 74 | |||
| 75 | pub fn dump(air: Air, pt: Zcu.PerThread, liveness: ?Air.Liveness) void { | ||
| 76 | air.write(std.io.getStdErr().writer(), pt, liveness); | ||
| 77 | } | ||
| 78 | |||
| 79 | pub fn dumpInst(air: Air, inst: Air.Inst.Index, pt: Zcu.PerThread, liveness: ?Air.Liveness) void { | ||
| 80 | air.writeInst(std.io.getStdErr().writer(), inst, pt, liveness); | ||
| 81 | } | ||
| 82 | |||
| 83 | const Writer = struct { | ||
| 84 | pt: Zcu.PerThread, | ||
| 85 | gpa: Allocator, | ||
| 86 | air: Air, | ||
| 87 | liveness: ?Air.Liveness, | ||
| 88 | indent: usize, | ||
| 89 | skip_body: bool, | ||
| 90 | |||
| 91 | fn writeBody(w: *Writer, s: anytype, body: []const Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 92 | for (body) |inst| { | ||
| 93 | try w.writeInst(s, inst); | ||
| 94 | try s.writeByte('\n'); | ||
| 95 | } | ||
| 96 | } | ||
| 97 | |||
| 98 | fn writeInst(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 99 | const tag = w.air.instructions.items(.tag)[@intFromEnum(inst)]; | ||
| 100 | try s.writeByteNTimes(' ', w.indent); | ||
| 101 | try s.print("{}{c}= {s}(", .{ | ||
| 102 | inst, | ||
| 103 | @as(u8, if (if (w.liveness) |liveness| liveness.isUnused(inst) else false) '!' else ' '), | ||
| 104 | @tagName(tag), | ||
| 105 | }); | ||
| 106 | switch (tag) { | ||
| 107 | .add, | ||
| 108 | .add_optimized, | ||
| 109 | .add_safe, | ||
| 110 | .add_wrap, | ||
| 111 | .add_sat, | ||
| 112 | .sub, | ||
| 113 | .sub_optimized, | ||
| 114 | .sub_safe, | ||
| 115 | .sub_wrap, | ||
| 116 | .sub_sat, | ||
| 117 | .mul, | ||
| 118 | .mul_optimized, | ||
| 119 | .mul_safe, | ||
| 120 | .mul_wrap, | ||
| 121 | .mul_sat, | ||
| 122 | .div_float, | ||
| 123 | .div_trunc, | ||
| 124 | .div_floor, | ||
| 125 | .div_exact, | ||
| 126 | .rem, | ||
| 127 | .mod, | ||
| 128 | .bit_and, | ||
| 129 | .bit_or, | ||
| 130 | .xor, | ||
| 131 | .cmp_lt, | ||
| 132 | .cmp_lte, | ||
| 133 | .cmp_eq, | ||
| 134 | .cmp_gte, | ||
| 135 | .cmp_gt, | ||
| 136 | .cmp_neq, | ||
| 137 | .bool_and, | ||
| 138 | .bool_or, | ||
| 139 | .store, | ||
| 140 | .store_safe, | ||
| 141 | .array_elem_val, | ||
| 142 | .slice_elem_val, | ||
| 143 | .ptr_elem_val, | ||
| 144 | .shl, | ||
| 145 | .shl_exact, | ||
| 146 | .shl_sat, | ||
| 147 | .shr, | ||
| 148 | .shr_exact, | ||
| 149 | .set_union_tag, | ||
| 150 | .min, | ||
| 151 | .max, | ||
| 152 | .div_float_optimized, | ||
| 153 | .div_trunc_optimized, | ||
| 154 | .div_floor_optimized, | ||
| 155 | .div_exact_optimized, | ||
| 156 | .rem_optimized, | ||
| 157 | .mod_optimized, | ||
| 158 | .cmp_lt_optimized, | ||
| 159 | .cmp_lte_optimized, | ||
| 160 | .cmp_eq_optimized, | ||
| 161 | .cmp_gte_optimized, | ||
| 162 | .cmp_gt_optimized, | ||
| 163 | .cmp_neq_optimized, | ||
| 164 | .memcpy, | ||
| 165 | .memmove, | ||
| 166 | .memset, | ||
| 167 | .memset_safe, | ||
| 168 | => try w.writeBinOp(s, inst), | ||
| 169 | |||
| 170 | .is_null, | ||
| 171 | .is_non_null, | ||
| 172 | .is_null_ptr, | ||
| 173 | .is_non_null_ptr, | ||
| 174 | .is_err, | ||
| 175 | .is_non_err, | ||
| 176 | .is_err_ptr, | ||
| 177 | .is_non_err_ptr, | ||
| 178 | .ret, | ||
| 179 | .ret_safe, | ||
| 180 | .ret_load, | ||
| 181 | .is_named_enum_value, | ||
| 182 | .tag_name, | ||
| 183 | .error_name, | ||
| 184 | .sqrt, | ||
| 185 | .sin, | ||
| 186 | .cos, | ||
| 187 | .tan, | ||
| 188 | .exp, | ||
| 189 | .exp2, | ||
| 190 | .log, | ||
| 191 | .log2, | ||
| 192 | .log10, | ||
| 193 | .floor, | ||
| 194 | .ceil, | ||
| 195 | .round, | ||
| 196 | .trunc_float, | ||
| 197 | .neg, | ||
| 198 | .neg_optimized, | ||
| 199 | .cmp_lt_errors_len, | ||
| 200 | .set_err_return_trace, | ||
| 201 | .c_va_end, | ||
| 202 | => try w.writeUnOp(s, inst), | ||
| 203 | |||
| 204 | .trap, | ||
| 205 | .breakpoint, | ||
| 206 | .dbg_empty_stmt, | ||
| 207 | .unreach, | ||
| 208 | .ret_addr, | ||
| 209 | .frame_addr, | ||
| 210 | .save_err_return_trace_index, | ||
| 211 | => try w.writeNoOp(s, inst), | ||
| 212 | |||
| 213 | .alloc, | ||
| 214 | .ret_ptr, | ||
| 215 | .err_return_trace, | ||
| 216 | .c_va_start, | ||
| 217 | => try w.writeTy(s, inst), | ||
| 218 | |||
| 219 | .arg => try w.writeArg(s, inst), | ||
| 220 | |||
| 221 | .not, | ||
| 222 | .bitcast, | ||
| 223 | .load, | ||
| 224 | .fptrunc, | ||
| 225 | .fpext, | ||
| 226 | .intcast, | ||
| 227 | .intcast_safe, | ||
| 228 | .trunc, | ||
| 229 | .optional_payload, | ||
| 230 | .optional_payload_ptr, | ||
| 231 | .optional_payload_ptr_set, | ||
| 232 | .errunion_payload_ptr_set, | ||
| 233 | .wrap_optional, | ||
| 234 | .unwrap_errunion_payload, | ||
| 235 | .unwrap_errunion_err, | ||
| 236 | .unwrap_errunion_payload_ptr, | ||
| 237 | .unwrap_errunion_err_ptr, | ||
| 238 | .wrap_errunion_payload, | ||
| 239 | .wrap_errunion_err, | ||
| 240 | .slice_ptr, | ||
| 241 | .slice_len, | ||
| 242 | .ptr_slice_len_ptr, | ||
| 243 | .ptr_slice_ptr_ptr, | ||
| 244 | .struct_field_ptr_index_0, | ||
| 245 | .struct_field_ptr_index_1, | ||
| 246 | .struct_field_ptr_index_2, | ||
| 247 | .struct_field_ptr_index_3, | ||
| 248 | .array_to_slice, | ||
| 249 | .float_from_int, | ||
| 250 | .splat, | ||
| 251 | .int_from_float, | ||
| 252 | .int_from_float_optimized, | ||
| 253 | .get_union_tag, | ||
| 254 | .clz, | ||
| 255 | .ctz, | ||
| 256 | .popcount, | ||
| 257 | .byte_swap, | ||
| 258 | .bit_reverse, | ||
| 259 | .abs, | ||
| 260 | .error_set_has_value, | ||
| 261 | .addrspace_cast, | ||
| 262 | .c_va_arg, | ||
| 263 | .c_va_copy, | ||
| 264 | => try w.writeTyOp(s, inst), | ||
| 265 | |||
| 266 | .block, .dbg_inline_block => try w.writeBlock(s, tag, inst), | ||
| 267 | |||
| 268 | .loop => try w.writeLoop(s, inst), | ||
| 269 | |||
| 270 | .slice, | ||
| 271 | .slice_elem_ptr, | ||
| 272 | .ptr_elem_ptr, | ||
| 273 | .ptr_add, | ||
| 274 | .ptr_sub, | ||
| 275 | .add_with_overflow, | ||
| 276 | .sub_with_overflow, | ||
| 277 | .mul_with_overflow, | ||
| 278 | .shl_with_overflow, | ||
| 279 | => try w.writeTyPlBin(s, inst), | ||
| 280 | |||
| 281 | .call, | ||
| 282 | .call_always_tail, | ||
| 283 | .call_never_tail, | ||
| 284 | .call_never_inline, | ||
| 285 | => try w.writeCall(s, inst), | ||
| 286 | |||
| 287 | .dbg_var_ptr, | ||
| 288 | .dbg_var_val, | ||
| 289 | .dbg_arg_inline, | ||
| 290 | => try w.writeDbgVar(s, inst), | ||
| 291 | |||
| 292 | .struct_field_ptr => try w.writeStructField(s, inst), | ||
| 293 | .struct_field_val => try w.writeStructField(s, inst), | ||
| 294 | .inferred_alloc => @panic("TODO"), | ||
| 295 | .inferred_alloc_comptime => @panic("TODO"), | ||
| 296 | .assembly => try w.writeAssembly(s, inst), | ||
| 297 | .dbg_stmt => try w.writeDbgStmt(s, inst), | ||
| 298 | |||
| 299 | .aggregate_init => try w.writeAggregateInit(s, inst), | ||
| 300 | .union_init => try w.writeUnionInit(s, inst), | ||
| 301 | .br => try w.writeBr(s, inst), | ||
| 302 | .switch_dispatch => try w.writeBr(s, inst), | ||
| 303 | .repeat => try w.writeRepeat(s, inst), | ||
| 304 | .cond_br => try w.writeCondBr(s, inst), | ||
| 305 | .@"try", .try_cold => try w.writeTry(s, inst), | ||
| 306 | .try_ptr, .try_ptr_cold => try w.writeTryPtr(s, inst), | ||
| 307 | .loop_switch_br, .switch_br => try w.writeSwitchBr(s, inst), | ||
| 308 | .cmpxchg_weak, .cmpxchg_strong => try w.writeCmpxchg(s, inst), | ||
| 309 | .atomic_load => try w.writeAtomicLoad(s, inst), | ||
| 310 | .prefetch => try w.writePrefetch(s, inst), | ||
| 311 | .atomic_store_unordered => try w.writeAtomicStore(s, inst, .unordered), | ||
| 312 | .atomic_store_monotonic => try w.writeAtomicStore(s, inst, .monotonic), | ||
| 313 | .atomic_store_release => try w.writeAtomicStore(s, inst, .release), | ||
| 314 | .atomic_store_seq_cst => try w.writeAtomicStore(s, inst, .seq_cst), | ||
| 315 | .atomic_rmw => try w.writeAtomicRmw(s, inst), | ||
| 316 | .field_parent_ptr => try w.writeFieldParentPtr(s, inst), | ||
| 317 | .wasm_memory_size => try w.writeWasmMemorySize(s, inst), | ||
| 318 | .wasm_memory_grow => try w.writeWasmMemoryGrow(s, inst), | ||
| 319 | .mul_add => try w.writeMulAdd(s, inst), | ||
| 320 | .select => try w.writeSelect(s, inst), | ||
| 321 | .shuffle_one => try w.writeShuffleOne(s, inst), | ||
| 322 | .shuffle_two => try w.writeShuffleTwo(s, inst), | ||
| 323 | .reduce, .reduce_optimized => try w.writeReduce(s, inst), | ||
| 324 | .cmp_vector, .cmp_vector_optimized => try w.writeCmpVector(s, inst), | ||
| 325 | .vector_store_elem => try w.writeVectorStoreElem(s, inst), | ||
| 326 | .runtime_nav_ptr => try w.writeRuntimeNavPtr(s, inst), | ||
| 327 | |||
| 328 | .work_item_id, | ||
| 329 | .work_group_size, | ||
| 330 | .work_group_id, | ||
| 331 | => try w.writeWorkDimension(s, inst), | ||
| 332 | } | ||
| 333 | try s.writeByte(')'); | ||
| 334 | } | ||
| 335 | |||
| 336 | fn writeBinOp(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 337 | const bin_op = w.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; | ||
| 338 | try w.writeOperand(s, inst, 0, bin_op.lhs); | ||
| 339 | try s.writeAll(", "); | ||
| 340 | try w.writeOperand(s, inst, 1, bin_op.rhs); | ||
| 341 | } | ||
| 342 | |||
| 343 | fn writeUnOp(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 344 | const un_op = w.air.instructions.items(.data)[@intFromEnum(inst)].un_op; | ||
| 345 | try w.writeOperand(s, inst, 0, un_op); | ||
| 346 | } | ||
| 347 | |||
| 348 | fn writeNoOp(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 349 | _ = w; | ||
| 350 | _ = inst; | ||
| 351 | // no-op, no argument to write | ||
| 352 | } | ||
| 353 | |||
| 354 | fn writeType(w: *Writer, s: anytype, ty: Type) !void { | ||
| 355 | return ty.print(s, w.pt); | ||
| 356 | } | ||
| 357 | |||
| 358 | fn writeTy(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 359 | const ty = w.air.instructions.items(.data)[@intFromEnum(inst)].ty; | ||
| 360 | try w.writeType(s, ty); | ||
| 361 | } | ||
| 362 | |||
| 363 | fn writeArg(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 364 | const arg = w.air.instructions.items(.data)[@intFromEnum(inst)].arg; | ||
| 365 | try w.writeType(s, arg.ty.toType()); | ||
| 366 | switch (arg.name) { | ||
| 367 | .none => {}, | ||
| 368 | _ => try s.print(", \"{}\"", .{std.zig.fmtEscapes(arg.name.toSlice(w.air))}), | ||
| 369 | } | ||
| 370 | } | ||
| 371 | |||
| 372 | fn writeTyOp(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 373 | const ty_op = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; | ||
| 374 | try w.writeType(s, ty_op.ty.toType()); | ||
| 375 | try s.writeAll(", "); | ||
| 376 | try w.writeOperand(s, inst, 0, ty_op.operand); | ||
| 377 | } | ||
| 378 | |||
| 379 | fn writeBlock(w: *Writer, s: anytype, tag: Air.Inst.Tag, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 380 | const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; | ||
| 381 | try w.writeType(s, ty_pl.ty.toType()); | ||
| 382 | const body: []const Air.Inst.Index = @ptrCast(switch (tag) { | ||
| 383 | inline .block, .dbg_inline_block => |comptime_tag| body: { | ||
| 384 | const extra = w.air.extraData(switch (comptime_tag) { | ||
| 385 | .block => Air.Block, | ||
| 386 | .dbg_inline_block => Air.DbgInlineBlock, | ||
| 387 | else => unreachable, | ||
| 388 | }, ty_pl.payload); | ||
| 389 | switch (comptime_tag) { | ||
| 390 | .block => {}, | ||
| 391 | .dbg_inline_block => { | ||
| 392 | try s.writeAll(", "); | ||
| 393 | try w.writeInstRef(s, Air.internedToRef(extra.data.func), false); | ||
| 394 | }, | ||
| 395 | else => unreachable, | ||
| 396 | } | ||
| 397 | break :body w.air.extra.items[extra.end..][0..extra.data.body_len]; | ||
| 398 | }, | ||
| 399 | else => unreachable, | ||
| 400 | }); | ||
| 401 | if (w.skip_body) return s.writeAll(", ..."); | ||
| 402 | const liveness_block: Air.Liveness.BlockSlices = if (w.liveness) |liveness| | ||
| 403 | liveness.getBlock(inst) | ||
| 404 | else | ||
| 405 | .{ .deaths = &.{} }; | ||
| 406 | |||
| 407 | try s.writeAll(", {\n"); | ||
| 408 | const old_indent = w.indent; | ||
| 409 | w.indent += 2; | ||
| 410 | try w.writeBody(s, body); | ||
| 411 | w.indent = old_indent; | ||
| 412 | try s.writeByteNTimes(' ', w.indent); | ||
| 413 | try s.writeAll("}"); | ||
| 414 | |||
| 415 | for (liveness_block.deaths) |operand| { | ||
| 416 | try s.print(" {}!", .{operand}); | ||
| 417 | } | ||
| 418 | } | ||
| 419 | |||
| 420 | fn writeLoop(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 421 | const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; | ||
| 422 | const extra = w.air.extraData(Air.Block, ty_pl.payload); | ||
| 423 | const body: []const Air.Inst.Index = @ptrCast(w.air.extra.items[extra.end..][0..extra.data.body_len]); | ||
| 424 | |||
| 425 | try w.writeType(s, ty_pl.ty.toType()); | ||
| 426 | if (w.skip_body) return s.writeAll(", ..."); | ||
| 427 | try s.writeAll(", {\n"); | ||
| 428 | const old_indent = w.indent; | ||
| 429 | w.indent += 2; | ||
| 430 | try w.writeBody(s, body); | ||
| 431 | w.indent = old_indent; | ||
| 432 | try s.writeByteNTimes(' ', w.indent); | ||
| 433 | try s.writeAll("}"); | ||
| 434 | } | ||
| 435 | |||
| 436 | fn writeAggregateInit(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 437 | const zcu = w.pt.zcu; | ||
| 438 | const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; | ||
| 439 | const vector_ty = ty_pl.ty.toType(); | ||
| 440 | const len = @as(usize, @intCast(vector_ty.arrayLen(zcu))); | ||
| 441 | const elements = @as([]const Air.Inst.Ref, @ptrCast(w.air.extra.items[ty_pl.payload..][0..len])); | ||
| 442 | |||
| 443 | try w.writeType(s, vector_ty); | ||
| 444 | try s.writeAll(", ["); | ||
| 445 | for (elements, 0..) |elem, i| { | ||
| 446 | if (i != 0) try s.writeAll(", "); | ||
| 447 | try w.writeOperand(s, inst, i, elem); | ||
| 448 | } | ||
| 449 | try s.writeAll("]"); | ||
| 450 | } | ||
| 451 | |||
| 452 | fn writeUnionInit(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 453 | const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; | ||
| 454 | const extra = w.air.extraData(Air.UnionInit, ty_pl.payload).data; | ||
| 455 | |||
| 456 | try s.print("{d}, ", .{extra.field_index}); | ||
| 457 | try w.writeOperand(s, inst, 0, extra.init); | ||
| 458 | } | ||
| 459 | |||
| 460 | fn writeStructField(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 461 | const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; | ||
| 462 | const extra = w.air.extraData(Air.StructField, ty_pl.payload).data; | ||
| 463 | |||
| 464 | try w.writeOperand(s, inst, 0, extra.struct_operand); | ||
| 465 | try s.print(", {d}", .{extra.field_index}); | ||
| 466 | } | ||
| 467 | |||
| 468 | fn writeTyPlBin(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 469 | const data = w.air.instructions.items(.data); | ||
| 470 | const ty_pl = data[@intFromEnum(inst)].ty_pl; | ||
| 471 | const extra = w.air.extraData(Air.Bin, ty_pl.payload).data; | ||
| 472 | |||
| 473 | const inst_ty = data[@intFromEnum(inst)].ty_pl.ty.toType(); | ||
| 474 | try w.writeType(s, inst_ty); | ||
| 475 | try s.writeAll(", "); | ||
| 476 | try w.writeOperand(s, inst, 0, extra.lhs); | ||
| 477 | try s.writeAll(", "); | ||
| 478 | try w.writeOperand(s, inst, 1, extra.rhs); | ||
| 479 | } | ||
| 480 | |||
| 481 | fn writeCmpxchg(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 482 | const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; | ||
| 483 | const extra = w.air.extraData(Air.Cmpxchg, ty_pl.payload).data; | ||
| 484 | |||
| 485 | try w.writeOperand(s, inst, 0, extra.ptr); | ||
| 486 | try s.writeAll(", "); | ||
| 487 | try w.writeOperand(s, inst, 1, extra.expected_value); | ||
| 488 | try s.writeAll(", "); | ||
| 489 | try w.writeOperand(s, inst, 2, extra.new_value); | ||
| 490 | try s.print(", {s}, {s}", .{ | ||
| 491 | @tagName(extra.successOrder()), @tagName(extra.failureOrder()), | ||
| 492 | }); | ||
| 493 | } | ||
| 494 | |||
| 495 | fn writeMulAdd(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 496 | const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; | ||
| 497 | const extra = w.air.extraData(Air.Bin, pl_op.payload).data; | ||
| 498 | |||
| 499 | try w.writeOperand(s, inst, 0, extra.lhs); | ||
| 500 | try s.writeAll(", "); | ||
| 501 | try w.writeOperand(s, inst, 1, extra.rhs); | ||
| 502 | try s.writeAll(", "); | ||
| 503 | try w.writeOperand(s, inst, 2, pl_op.operand); | ||
| 504 | } | ||
| 505 | |||
| 506 | fn writeShuffleOne(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 507 | const unwrapped = w.air.unwrapShuffleOne(w.pt.zcu, inst); | ||
| 508 | try w.writeType(s, unwrapped.result_ty); | ||
| 509 | try s.writeAll(", "); | ||
| 510 | try w.writeOperand(s, inst, 0, unwrapped.operand); | ||
| 511 | try s.writeAll(", ["); | ||
| 512 | for (unwrapped.mask, 0..) |mask_elem, mask_idx| { | ||
| 513 | if (mask_idx > 0) try s.writeAll(", "); | ||
| 514 | switch (mask_elem.unwrap()) { | ||
| 515 | .elem => |idx| try s.print("elem {d}", .{idx}), | ||
| 516 | .value => |val| try s.print("val {}", .{Value.fromInterned(val).fmtValue(w.pt)}), | ||
| 517 | } | ||
| 518 | } | ||
| 519 | try s.writeByte(']'); | ||
| 520 | } | ||
| 521 | |||
| 522 | fn writeShuffleTwo(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 523 | const unwrapped = w.air.unwrapShuffleTwo(w.pt.zcu, inst); | ||
| 524 | try w.writeType(s, unwrapped.result_ty); | ||
| 525 | try s.writeAll(", "); | ||
| 526 | try w.writeOperand(s, inst, 0, unwrapped.operand_a); | ||
| 527 | try s.writeAll(", "); | ||
| 528 | try w.writeOperand(s, inst, 1, unwrapped.operand_b); | ||
| 529 | try s.writeAll(", ["); | ||
| 530 | for (unwrapped.mask, 0..) |mask_elem, mask_idx| { | ||
| 531 | if (mask_idx > 0) try s.writeAll(", "); | ||
| 532 | switch (mask_elem.unwrap()) { | ||
| 533 | .a_elem => |idx| try s.print("a_elem {d}", .{idx}), | ||
| 534 | .b_elem => |idx| try s.print("b_elem {d}", .{idx}), | ||
| 535 | .undef => try s.writeAll("undef"), | ||
| 536 | } | ||
| 537 | } | ||
| 538 | try s.writeByte(']'); | ||
| 539 | } | ||
| 540 | |||
| 541 | fn writeSelect(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 542 | const zcu = w.pt.zcu; | ||
| 543 | const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; | ||
| 544 | const extra = w.air.extraData(Air.Bin, pl_op.payload).data; | ||
| 545 | |||
| 546 | const elem_ty = w.typeOfIndex(inst).childType(zcu); | ||
| 547 | try w.writeType(s, elem_ty); | ||
| 548 | try s.writeAll(", "); | ||
| 549 | try w.writeOperand(s, inst, 0, pl_op.operand); | ||
| 550 | try s.writeAll(", "); | ||
| 551 | try w.writeOperand(s, inst, 1, extra.lhs); | ||
| 552 | try s.writeAll(", "); | ||
| 553 | try w.writeOperand(s, inst, 2, extra.rhs); | ||
| 554 | } | ||
| 555 | |||
| 556 | fn writeReduce(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 557 | const reduce = w.air.instructions.items(.data)[@intFromEnum(inst)].reduce; | ||
| 558 | |||
| 559 | try w.writeOperand(s, inst, 0, reduce.operand); | ||
| 560 | try s.print(", {s}", .{@tagName(reduce.operation)}); | ||
| 561 | } | ||
| 562 | |||
| 563 | fn writeCmpVector(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 564 | const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; | ||
| 565 | const extra = w.air.extraData(Air.VectorCmp, ty_pl.payload).data; | ||
| 566 | |||
| 567 | try s.print("{s}, ", .{@tagName(extra.compareOperator())}); | ||
| 568 | try w.writeOperand(s, inst, 0, extra.lhs); | ||
| 569 | try s.writeAll(", "); | ||
| 570 | try w.writeOperand(s, inst, 1, extra.rhs); | ||
| 571 | } | ||
| 572 | |||
| 573 | fn writeVectorStoreElem(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 574 | const data = w.air.instructions.items(.data)[@intFromEnum(inst)].vector_store_elem; | ||
| 575 | const extra = w.air.extraData(Air.VectorCmp, data.payload).data; | ||
| 576 | |||
| 577 | try w.writeOperand(s, inst, 0, data.vector_ptr); | ||
| 578 | try s.writeAll(", "); | ||
| 579 | try w.writeOperand(s, inst, 1, extra.lhs); | ||
| 580 | try s.writeAll(", "); | ||
| 581 | try w.writeOperand(s, inst, 2, extra.rhs); | ||
| 582 | } | ||
| 583 | |||
| 584 | fn writeRuntimeNavPtr(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 585 | const ip = &w.pt.zcu.intern_pool; | ||
| 586 | const ty_nav = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_nav; | ||
| 587 | try w.writeType(s, .fromInterned(ty_nav.ty)); | ||
| 588 | try s.print(", '{}'", .{ip.getNav(ty_nav.nav).fqn.fmt(ip)}); | ||
| 589 | } | ||
| 590 | |||
| 591 | fn writeAtomicLoad(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 592 | const atomic_load = w.air.instructions.items(.data)[@intFromEnum(inst)].atomic_load; | ||
| 593 | |||
| 594 | try w.writeOperand(s, inst, 0, atomic_load.ptr); | ||
| 595 | try s.print(", {s}", .{@tagName(atomic_load.order)}); | ||
| 596 | } | ||
| 597 | |||
| 598 | fn writePrefetch(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 599 | const prefetch = w.air.instructions.items(.data)[@intFromEnum(inst)].prefetch; | ||
| 600 | |||
| 601 | try w.writeOperand(s, inst, 0, prefetch.ptr); | ||
| 602 | try s.print(", {s}, {d}, {s}", .{ | ||
| 603 | @tagName(prefetch.rw), prefetch.locality, @tagName(prefetch.cache), | ||
| 604 | }); | ||
| 605 | } | ||
| 606 | |||
| 607 | fn writeAtomicStore( | ||
| 608 | w: *Writer, | ||
| 609 | s: anytype, | ||
| 610 | inst: Air.Inst.Index, | ||
| 611 | order: std.builtin.AtomicOrder, | ||
| 612 | ) @TypeOf(s).Error!void { | ||
| 613 | const bin_op = w.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; | ||
| 614 | try w.writeOperand(s, inst, 0, bin_op.lhs); | ||
| 615 | try s.writeAll(", "); | ||
| 616 | try w.writeOperand(s, inst, 1, bin_op.rhs); | ||
| 617 | try s.print(", {s}", .{@tagName(order)}); | ||
| 618 | } | ||
| 619 | |||
| 620 | fn writeAtomicRmw(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 621 | const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; | ||
| 622 | const extra = w.air.extraData(Air.AtomicRmw, pl_op.payload).data; | ||
| 623 | |||
| 624 | try w.writeOperand(s, inst, 0, pl_op.operand); | ||
| 625 | try s.writeAll(", "); | ||
| 626 | try w.writeOperand(s, inst, 1, extra.operand); | ||
| 627 | try s.print(", {s}, {s}", .{ @tagName(extra.op()), @tagName(extra.ordering()) }); | ||
| 628 | } | ||
| 629 | |||
| 630 | fn writeFieldParentPtr(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 631 | const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; | ||
| 632 | const extra = w.air.extraData(Air.FieldParentPtr, ty_pl.payload).data; | ||
| 633 | |||
| 634 | try w.writeOperand(s, inst, 0, extra.field_ptr); | ||
| 635 | try s.print(", {d}", .{extra.field_index}); | ||
| 636 | } | ||
| 637 | |||
| 638 | fn writeAssembly(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 639 | const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; | ||
| 640 | const extra = w.air.extraData(Air.Asm, ty_pl.payload); | ||
| 641 | const is_volatile = @as(u1, @truncate(extra.data.flags >> 31)) != 0; | ||
| 642 | const clobbers_len = @as(u31, @truncate(extra.data.flags)); | ||
| 643 | var extra_i: usize = extra.end; | ||
| 644 | var op_index: usize = 0; | ||
| 645 | |||
| 646 | const ret_ty = w.typeOfIndex(inst); | ||
| 647 | try w.writeType(s, ret_ty); | ||
| 648 | |||
| 649 | if (is_volatile) { | ||
| 650 | try s.writeAll(", volatile"); | ||
| 651 | } | ||
| 652 | |||
| 653 | const outputs = @as([]const Air.Inst.Ref, @ptrCast(w.air.extra.items[extra_i..][0..extra.data.outputs_len])); | ||
| 654 | extra_i += outputs.len; | ||
| 655 | const inputs = @as([]const Air.Inst.Ref, @ptrCast(w.air.extra.items[extra_i..][0..extra.data.inputs_len])); | ||
| 656 | extra_i += inputs.len; | ||
| 657 | |||
| 658 | for (outputs) |output| { | ||
| 659 | const extra_bytes = std.mem.sliceAsBytes(w.air.extra.items[extra_i..]); | ||
| 660 | const constraint = std.mem.sliceTo(extra_bytes, 0); | ||
| 661 | const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0); | ||
| 662 | |||
| 663 | // This equation accounts for the fact that even if we have exactly 4 bytes | ||
| 664 | // for the strings and their null terminators, we still use the next u32 | ||
| 665 | // for the null terminator. | ||
| 666 | extra_i += (constraint.len + name.len + (2 + 3)) / 4; | ||
| 667 | |||
| 668 | if (output == .none) { | ||
| 669 | try s.print(", [{s}] -> {s}", .{ name, constraint }); | ||
| 670 | } else { | ||
| 671 | try s.print(", [{s}] out {s} = (", .{ name, constraint }); | ||
| 672 | try w.writeOperand(s, inst, op_index, output); | ||
| 673 | op_index += 1; | ||
| 674 | try s.writeByte(')'); | ||
| 675 | } | ||
| 676 | } | ||
| 677 | |||
| 678 | for (inputs) |input| { | ||
| 679 | const extra_bytes = std.mem.sliceAsBytes(w.air.extra.items[extra_i..]); | ||
| 680 | const constraint = std.mem.sliceTo(extra_bytes, 0); | ||
| 681 | const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0); | ||
| 682 | // This equation accounts for the fact that even if we have exactly 4 bytes | ||
| 683 | // for the strings and their null terminators, we still use the next u32 | ||
| 684 | // for the null terminator. | ||
| 685 | extra_i += (constraint.len + name.len + 1) / 4 + 1; | ||
| 686 | |||
| 687 | try s.print(", [{s}] in {s} = (", .{ name, constraint }); | ||
| 688 | try w.writeOperand(s, inst, op_index, input); | ||
| 689 | op_index += 1; | ||
| 690 | try s.writeByte(')'); | ||
| 691 | } | ||
| 692 | |||
| 693 | { | ||
| 694 | var clobber_i: u32 = 0; | ||
| 695 | while (clobber_i < clobbers_len) : (clobber_i += 1) { | ||
| 696 | const extra_bytes = std.mem.sliceAsBytes(w.air.extra.items[extra_i..]); | ||
| 697 | const clobber = std.mem.sliceTo(extra_bytes, 0); | ||
| 698 | // This equation accounts for the fact that even if we have exactly 4 bytes | ||
| 699 | // for the string, we still use the next u32 for the null terminator. | ||
| 700 | extra_i += clobber.len / 4 + 1; | ||
| 701 | |||
| 702 | try s.writeAll(", ~{"); | ||
| 703 | try s.writeAll(clobber); | ||
| 704 | try s.writeAll("}"); | ||
| 705 | } | ||
| 706 | } | ||
| 707 | const asm_source = std.mem.sliceAsBytes(w.air.extra.items[extra_i..])[0..extra.data.source_len]; | ||
| 708 | try s.print(", \"{}\"", .{std.zig.fmtEscapes(asm_source)}); | ||
| 709 | } | ||
| 710 | |||
| 711 | fn writeDbgStmt(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 712 | const dbg_stmt = w.air.instructions.items(.data)[@intFromEnum(inst)].dbg_stmt; | ||
| 713 | try s.print("{d}:{d}", .{ dbg_stmt.line + 1, dbg_stmt.column + 1 }); | ||
| 714 | } | ||
| 715 | |||
| 716 | fn writeDbgVar(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 717 | const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; | ||
| 718 | try w.writeOperand(s, inst, 0, pl_op.operand); | ||
| 719 | const name: Air.NullTerminatedString = @enumFromInt(pl_op.payload); | ||
| 720 | try s.print(", \"{}\"", .{std.zig.fmtEscapes(name.toSlice(w.air))}); | ||
| 721 | } | ||
| 722 | |||
| 723 | fn writeCall(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 724 | const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; | ||
| 725 | const extra = w.air.extraData(Air.Call, pl_op.payload); | ||
| 726 | const args = @as([]const Air.Inst.Ref, @ptrCast(w.air.extra.items[extra.end..][0..extra.data.args_len])); | ||
| 727 | try w.writeOperand(s, inst, 0, pl_op.operand); | ||
| 728 | try s.writeAll(", ["); | ||
| 729 | for (args, 0..) |arg, i| { | ||
| 730 | if (i != 0) try s.writeAll(", "); | ||
| 731 | try w.writeOperand(s, inst, 1 + i, arg); | ||
| 732 | } | ||
| 733 | try s.writeAll("]"); | ||
| 734 | } | ||
| 735 | |||
| 736 | fn writeBr(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 737 | const br = w.air.instructions.items(.data)[@intFromEnum(inst)].br; | ||
| 738 | try w.writeInstIndex(s, br.block_inst, false); | ||
| 739 | try s.writeAll(", "); | ||
| 740 | try w.writeOperand(s, inst, 0, br.operand); | ||
| 741 | } | ||
| 742 | |||
| 743 | fn writeRepeat(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 744 | const repeat = w.air.instructions.items(.data)[@intFromEnum(inst)].repeat; | ||
| 745 | try w.writeInstIndex(s, repeat.loop_inst, false); | ||
| 746 | } | ||
| 747 | |||
| 748 | fn writeTry(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 749 | const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; | ||
| 750 | const extra = w.air.extraData(Air.Try, pl_op.payload); | ||
| 751 | const body: []const Air.Inst.Index = @ptrCast(w.air.extra.items[extra.end..][0..extra.data.body_len]); | ||
| 752 | const liveness_condbr: Air.Liveness.CondBrSlices = if (w.liveness) |liveness| | ||
| 753 | liveness.getCondBr(inst) | ||
| 754 | else | ||
| 755 | .{ .then_deaths = &.{}, .else_deaths = &.{} }; | ||
| 756 | |||
| 757 | try w.writeOperand(s, inst, 0, pl_op.operand); | ||
| 758 | if (w.skip_body) return s.writeAll(", ..."); | ||
| 759 | try s.writeAll(", {\n"); | ||
| 760 | const old_indent = w.indent; | ||
| 761 | w.indent += 2; | ||
| 762 | |||
| 763 | if (liveness_condbr.else_deaths.len != 0) { | ||
| 764 | try s.writeByteNTimes(' ', w.indent); | ||
| 765 | for (liveness_condbr.else_deaths, 0..) |operand, i| { | ||
| 766 | if (i != 0) try s.writeAll(" "); | ||
| 767 | try s.print("{}!", .{operand}); | ||
| 768 | } | ||
| 769 | try s.writeAll("\n"); | ||
| 770 | } | ||
| 771 | try w.writeBody(s, body); | ||
| 772 | |||
| 773 | w.indent = old_indent; | ||
| 774 | try s.writeByteNTimes(' ', w.indent); | ||
| 775 | try s.writeAll("}"); | ||
| 776 | |||
| 777 | for (liveness_condbr.then_deaths) |operand| { | ||
| 778 | try s.print(" {}!", .{operand}); | ||
| 779 | } | ||
| 780 | } | ||
| 781 | |||
| 782 | fn writeTryPtr(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 783 | const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; | ||
| 784 | const extra = w.air.extraData(Air.TryPtr, ty_pl.payload); | ||
| 785 | const body: []const Air.Inst.Index = @ptrCast(w.air.extra.items[extra.end..][0..extra.data.body_len]); | ||
| 786 | const liveness_condbr: Air.Liveness.CondBrSlices = if (w.liveness) |liveness| | ||
| 787 | liveness.getCondBr(inst) | ||
| 788 | else | ||
| 789 | .{ .then_deaths = &.{}, .else_deaths = &.{} }; | ||
| 790 | |||
| 791 | try w.writeOperand(s, inst, 0, extra.data.ptr); | ||
| 792 | |||
| 793 | try s.writeAll(", "); | ||
| 794 | try w.writeType(s, ty_pl.ty.toType()); | ||
| 795 | if (w.skip_body) return s.writeAll(", ..."); | ||
| 796 | try s.writeAll(", {\n"); | ||
| 797 | const old_indent = w.indent; | ||
| 798 | w.indent += 2; | ||
| 799 | |||
| 800 | if (liveness_condbr.else_deaths.len != 0) { | ||
| 801 | try s.writeByteNTimes(' ', w.indent); | ||
| 802 | for (liveness_condbr.else_deaths, 0..) |operand, i| { | ||
| 803 | if (i != 0) try s.writeAll(" "); | ||
| 804 | try s.print("{}!", .{operand}); | ||
| 805 | } | ||
| 806 | try s.writeAll("\n"); | ||
| 807 | } | ||
| 808 | try w.writeBody(s, body); | ||
| 809 | |||
| 810 | w.indent = old_indent; | ||
| 811 | try s.writeByteNTimes(' ', w.indent); | ||
| 812 | try s.writeAll("}"); | ||
| 813 | |||
| 814 | for (liveness_condbr.then_deaths) |operand| { | ||
| 815 | try s.print(" {}!", .{operand}); | ||
| 816 | } | ||
| 817 | } | ||
| 818 | |||
| 819 | fn writeCondBr(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 820 | const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; | ||
| 821 | const extra = w.air.extraData(Air.CondBr, pl_op.payload); | ||
| 822 | const then_body: []const Air.Inst.Index = @ptrCast(w.air.extra.items[extra.end..][0..extra.data.then_body_len]); | ||
| 823 | const else_body: []const Air.Inst.Index = @ptrCast(w.air.extra.items[extra.end + then_body.len ..][0..extra.data.else_body_len]); | ||
| 824 | const liveness_condbr: Air.Liveness.CondBrSlices = if (w.liveness) |liveness| | ||
| 825 | liveness.getCondBr(inst) | ||
| 826 | else | ||
| 827 | .{ .then_deaths = &.{}, .else_deaths = &.{} }; | ||
| 828 | |||
| 829 | try w.writeOperand(s, inst, 0, pl_op.operand); | ||
| 830 | if (w.skip_body) return s.writeAll(", ..."); | ||
| 831 | try s.writeAll(","); | ||
| 832 | if (extra.data.branch_hints.true != .none) { | ||
| 833 | try s.print(" {s}", .{@tagName(extra.data.branch_hints.true)}); | ||
| 834 | } | ||
| 835 | if (extra.data.branch_hints.then_cov != .none) { | ||
| 836 | try s.print(" {s}", .{@tagName(extra.data.branch_hints.then_cov)}); | ||
| 837 | } | ||
| 838 | try s.writeAll(" {\n"); | ||
| 839 | const old_indent = w.indent; | ||
| 840 | w.indent += 2; | ||
| 841 | |||
| 842 | if (liveness_condbr.then_deaths.len != 0) { | ||
| 843 | try s.writeByteNTimes(' ', w.indent); | ||
| 844 | for (liveness_condbr.then_deaths, 0..) |operand, i| { | ||
| 845 | if (i != 0) try s.writeAll(" "); | ||
| 846 | try s.print("{}!", .{operand}); | ||
| 847 | } | ||
| 848 | try s.writeAll("\n"); | ||
| 849 | } | ||
| 850 | |||
| 851 | try w.writeBody(s, then_body); | ||
| 852 | try s.writeByteNTimes(' ', old_indent); | ||
| 853 | try s.writeAll("},"); | ||
| 854 | if (extra.data.branch_hints.false != .none) { | ||
| 855 | try s.print(" {s}", .{@tagName(extra.data.branch_hints.false)}); | ||
| 856 | } | ||
| 857 | if (extra.data.branch_hints.else_cov != .none) { | ||
| 858 | try s.print(" {s}", .{@tagName(extra.data.branch_hints.else_cov)}); | ||
| 859 | } | ||
| 860 | try s.writeAll(" {\n"); | ||
| 861 | |||
| 862 | if (liveness_condbr.else_deaths.len != 0) { | ||
| 863 | try s.writeByteNTimes(' ', w.indent); | ||
| 864 | for (liveness_condbr.else_deaths, 0..) |operand, i| { | ||
| 865 | if (i != 0) try s.writeAll(" "); | ||
| 866 | try s.print("{}!", .{operand}); | ||
| 867 | } | ||
| 868 | try s.writeAll("\n"); | ||
| 869 | } | ||
| 870 | |||
| 871 | try w.writeBody(s, else_body); | ||
| 872 | w.indent = old_indent; | ||
| 873 | |||
| 874 | try s.writeByteNTimes(' ', old_indent); | ||
| 875 | try s.writeAll("}"); | ||
| 876 | } | ||
| 877 | |||
| 878 | fn writeSwitchBr(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 879 | const switch_br = w.air.unwrapSwitch(inst); | ||
| 880 | |||
| 881 | const liveness: Air.Liveness.SwitchBrTable = if (w.liveness) |liveness| | ||
| 882 | liveness.getSwitchBr(w.gpa, inst, switch_br.cases_len + 1) catch | ||
| 883 | @panic("out of memory") | ||
| 884 | else blk: { | ||
| 885 | const slice = w.gpa.alloc([]const Air.Inst.Index, switch_br.cases_len + 1) catch | ||
| 886 | @panic("out of memory"); | ||
| 887 | @memset(slice, &.{}); | ||
| 888 | break :blk .{ .deaths = slice }; | ||
| 889 | }; | ||
| 890 | defer w.gpa.free(liveness.deaths); | ||
| 891 | |||
| 892 | try w.writeOperand(s, inst, 0, switch_br.operand); | ||
| 893 | if (w.skip_body) return s.writeAll(", ..."); | ||
| 894 | const old_indent = w.indent; | ||
| 895 | w.indent += 2; | ||
| 896 | |||
| 897 | var it = switch_br.iterateCases(); | ||
| 898 | while (it.next()) |case| { | ||
| 899 | try s.writeAll(", ["); | ||
| 900 | for (case.items, 0..) |item, item_i| { | ||
| 901 | if (item_i != 0) try s.writeAll(", "); | ||
| 902 | try w.writeInstRef(s, item, false); | ||
| 903 | } | ||
| 904 | for (case.ranges, 0..) |range, range_i| { | ||
| 905 | if (range_i != 0 or case.items.len != 0) try s.writeAll(", "); | ||
| 906 | try w.writeInstRef(s, range[0], false); | ||
| 907 | try s.writeAll("..."); | ||
| 908 | try w.writeInstRef(s, range[1], false); | ||
| 909 | } | ||
| 910 | try s.writeAll("] "); | ||
| 911 | const hint = switch_br.getHint(case.idx); | ||
| 912 | if (hint != .none) { | ||
| 913 | try s.print(".{s} ", .{@tagName(hint)}); | ||
| 914 | } | ||
| 915 | try s.writeAll("=> {\n"); | ||
| 916 | w.indent += 2; | ||
| 917 | |||
| 918 | const deaths = liveness.deaths[case.idx]; | ||
| 919 | if (deaths.len != 0) { | ||
| 920 | try s.writeByteNTimes(' ', w.indent); | ||
| 921 | for (deaths, 0..) |operand, i| { | ||
| 922 | if (i != 0) try s.writeAll(" "); | ||
| 923 | try s.print("{}!", .{operand}); | ||
| 924 | } | ||
| 925 | try s.writeAll("\n"); | ||
| 926 | } | ||
| 927 | |||
| 928 | try w.writeBody(s, case.body); | ||
| 929 | w.indent -= 2; | ||
| 930 | try s.writeByteNTimes(' ', w.indent); | ||
| 931 | try s.writeAll("}"); | ||
| 932 | } | ||
| 933 | |||
| 934 | const else_body = it.elseBody(); | ||
| 935 | if (else_body.len != 0) { | ||
| 936 | try s.writeAll(", else "); | ||
| 937 | const hint = switch_br.getElseHint(); | ||
| 938 | if (hint != .none) { | ||
| 939 | try s.print(".{s} ", .{@tagName(hint)}); | ||
| 940 | } | ||
| 941 | try s.writeAll("=> {\n"); | ||
| 942 | w.indent += 2; | ||
| 943 | |||
| 944 | const deaths = liveness.deaths[liveness.deaths.len - 1]; | ||
| 945 | if (deaths.len != 0) { | ||
| 946 | try s.writeByteNTimes(' ', w.indent); | ||
| 947 | for (deaths, 0..) |operand, i| { | ||
| 948 | if (i != 0) try s.writeAll(" "); | ||
| 949 | try s.print("{}!", .{operand}); | ||
| 950 | } | ||
| 951 | try s.writeAll("\n"); | ||
| 952 | } | ||
| 953 | |||
| 954 | try w.writeBody(s, else_body); | ||
| 955 | w.indent -= 2; | ||
| 956 | try s.writeByteNTimes(' ', w.indent); | ||
| 957 | try s.writeAll("}"); | ||
| 958 | } | ||
| 959 | |||
| 960 | try s.writeAll("\n"); | ||
| 961 | try s.writeByteNTimes(' ', old_indent); | ||
| 962 | } | ||
| 963 | |||
| 964 | fn writeWasmMemorySize(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 965 | const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; | ||
| 966 | try s.print("{d}", .{pl_op.payload}); | ||
| 967 | } | ||
| 968 | |||
| 969 | fn writeWasmMemoryGrow(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 970 | const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; | ||
| 971 | try s.print("{d}, ", .{pl_op.payload}); | ||
| 972 | try w.writeOperand(s, inst, 0, pl_op.operand); | ||
| 973 | } | ||
| 974 | |||
| 975 | fn writeWorkDimension(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 976 | const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; | ||
| 977 | try s.print("{d}", .{pl_op.payload}); | ||
| 978 | } | ||
| 979 | |||
| 980 | fn writeOperand( | ||
| 981 | w: *Writer, | ||
| 982 | s: anytype, | ||
| 983 | inst: Air.Inst.Index, | ||
| 984 | op_index: usize, | ||
| 985 | operand: Air.Inst.Ref, | ||
| 986 | ) @TypeOf(s).Error!void { | ||
| 987 | const small_tomb_bits = Air.Liveness.bpi - 1; | ||
| 988 | const dies = if (w.liveness) |liveness| blk: { | ||
| 989 | if (op_index < small_tomb_bits) | ||
| 990 | break :blk liveness.operandDies(inst, @intCast(op_index)); | ||
| 991 | var extra_index = liveness.special.get(inst).?; | ||
| 992 | var tomb_op_index: usize = small_tomb_bits; | ||
| 993 | while (true) { | ||
| 994 | const bits = liveness.extra[extra_index]; | ||
| 995 | if (op_index < tomb_op_index + 31) { | ||
| 996 | break :blk @as(u1, @truncate(bits >> @as(u5, @intCast(op_index - tomb_op_index)))) != 0; | ||
| 997 | } | ||
| 998 | if ((bits >> 31) != 0) break :blk false; | ||
| 999 | extra_index += 1; | ||
| 1000 | tomb_op_index += 31; | ||
| 1001 | } | ||
| 1002 | } else false; | ||
| 1003 | return w.writeInstRef(s, operand, dies); | ||
| 1004 | } | ||
| 1005 | |||
| 1006 | fn writeInstRef( | ||
| 1007 | w: *Writer, | ||
| 1008 | s: anytype, | ||
| 1009 | operand: Air.Inst.Ref, | ||
| 1010 | dies: bool, | ||
| 1011 | ) @TypeOf(s).Error!void { | ||
| 1012 | if (@intFromEnum(operand) < InternPool.static_len) { | ||
| 1013 | return s.print("@{}", .{operand}); | ||
| 1014 | } else if (operand.toInterned()) |ip_index| { | ||
| 1015 | const pt = w.pt; | ||
| 1016 | const ty = Type.fromInterned(pt.zcu.intern_pool.indexToKey(ip_index).typeOf()); | ||
| 1017 | try s.print("<{}, {}>", .{ | ||
| 1018 | ty.fmt(pt), | ||
| 1019 | Value.fromInterned(ip_index).fmtValue(pt), | ||
| 1020 | }); | ||
| 1021 | } else { | ||
| 1022 | return w.writeInstIndex(s, operand.toIndex().?, dies); | ||
| 1023 | } | ||
| 1024 | } | ||
| 1025 | |||
| 1026 | fn writeInstIndex( | ||
| 1027 | w: *Writer, | ||
| 1028 | s: anytype, | ||
| 1029 | inst: Air.Inst.Index, | ||
| 1030 | dies: bool, | ||
| 1031 | ) @TypeOf(s).Error!void { | ||
| 1032 | _ = w; | ||
| 1033 | try s.print("{}", .{inst}); | ||
| 1034 | if (dies) try s.writeByte('!'); | ||
| 1035 | } | ||
| 1036 | |||
| 1037 | fn typeOfIndex(w: *Writer, inst: Air.Inst.Index) Type { | ||
| 1038 | const zcu = w.pt.zcu; | ||
| 1039 | return w.air.typeOfIndex(inst, &zcu.intern_pool); | ||
| 1040 | } | ||
| 1041 | }; | ||
src/Air/types_resolved.zig+1-1| ... | @@ -321,7 +321,7 @@ fn checkBody(air: Air, body: []const Air.Inst.Index, zcu: *Zcu) bool { | ... | @@ -321,7 +321,7 @@ fn checkBody(air: Air, body: []const Air.Inst.Index, zcu: *Zcu) bool { |
| 321 | if (!checkRef(bin.rhs, zcu)) return false; | 321 | if (!checkRef(bin.rhs, zcu)) return false; |
| 322 | }, | 322 | }, |
| 323 | 323 | ||
| 324 | .tlv_dllimport_ptr => { | 324 | .runtime_nav_ptr => { |
| 325 | if (!checkType(.fromInterned(data.ty_nav.ty), zcu)) return false; | 325 | if (!checkType(.fromInterned(data.ty_nav.ty), zcu)) return false; |
| 326 | }, | 326 | }, |
| 327 | 327 |
src/Compilation/Config.zig+19-12| ... | @@ -345,11 +345,19 @@ pub fn resolve(options: Options) ResolveError!Config { | ... | @@ -345,11 +345,19 @@ pub fn resolve(options: Options) ResolveError!Config { |
| 345 | } else false; | 345 | } else false; |
| 346 | }; | 346 | }; |
| 347 | 347 | ||
| 348 | const is_dyn_lib = switch (options.output_mode) { | ||
| 349 | .Obj, .Exe => false, | ||
| 350 | .Lib => link_mode == .dynamic, | ||
| 351 | }; | ||
| 352 | |||
| 348 | // Make a decision on whether to use LLVM backend for machine code generation. | 353 | // Make a decision on whether to use LLVM backend for machine code generation. |
| 349 | // Note that using the LLVM backend does not necessarily mean using LLVM libraries. | 354 | // Note that using the LLVM backend does not necessarily mean using LLVM libraries. |
| 350 | // For example, Zig can emit .bc and .ll files directly, and this is still considered | 355 | // For example, Zig can emit .bc and .ll files directly, and this is still considered |
| 351 | // using "the LLVM backend". | 356 | // using "the LLVM backend". |
| 352 | const prefer_llvm = b: { | 357 | const use_llvm = b: { |
| 358 | // If we have no zig code to compile, no need for LLVM. | ||
| 359 | if (!options.have_zcu) break :b false; | ||
| 360 | |||
| 353 | // If emitting to LLVM bitcode object format, must use LLVM backend. | 361 | // If emitting to LLVM bitcode object format, must use LLVM backend. |
| 354 | if (options.emit_llvm_ir or options.emit_llvm_bc) { | 362 | if (options.emit_llvm_ir or options.emit_llvm_bc) { |
| 355 | if (options.use_llvm == false) | 363 | if (options.use_llvm == false) |
| ... | @@ -382,9 +390,9 @@ pub fn resolve(options: Options) ResolveError!Config { | ... | @@ -382,9 +390,9 @@ pub fn resolve(options: Options) ResolveError!Config { |
| 382 | // Prefer LLVM for release builds. | 390 | // Prefer LLVM for release builds. |
| 383 | if (root_optimize_mode != .Debug) break :b true; | 391 | if (root_optimize_mode != .Debug) break :b true; |
| 384 | 392 | ||
| 385 | // Self-hosted backends can't handle the inline assembly in std.pie yet | 393 | // load_dynamic_library standalone test not passing on this combination |
| 386 | // https://github.com/ziglang/zig/issues/24046 | 394 | // https://github.com/ziglang/zig/issues/24080 |
| 387 | if (pie) break :b true; | 395 | if (target.os.tag == .macos and is_dyn_lib) break :b true; |
| 388 | 396 | ||
| 389 | // At this point we would prefer to use our own self-hosted backend, | 397 | // At this point we would prefer to use our own self-hosted backend, |
| 390 | // because the compilation speed is better than LLVM. But only do it if | 398 | // because the compilation speed is better than LLVM. But only do it if |
| ... | @@ -392,13 +400,6 @@ pub fn resolve(options: Options) ResolveError!Config { | ... | @@ -392,13 +400,6 @@ pub fn resolve(options: Options) ResolveError!Config { |
| 392 | break :b !target_util.selfHostedBackendIsAsRobustAsLlvm(target); | 400 | break :b !target_util.selfHostedBackendIsAsRobustAsLlvm(target); |
| 393 | }; | 401 | }; |
| 394 | 402 | ||
| 395 | const use_llvm = b: { | ||
| 396 | // If we have no zig code to compile, no need for LLVM. | ||
| 397 | if (!options.have_zcu) break :b false; | ||
| 398 | |||
| 399 | break :b prefer_llvm; | ||
| 400 | }; | ||
| 401 | |||
| 402 | if (options.emit_bin and options.have_zcu) { | 403 | if (options.emit_bin and options.have_zcu) { |
| 403 | if (!use_lib_llvm and use_llvm) { | 404 | if (!use_lib_llvm and use_llvm) { |
| 404 | // Explicit request to use LLVM to produce an object file, but without | 405 | // Explicit request to use LLVM to produce an object file, but without |
| ... | @@ -435,7 +436,13 @@ pub fn resolve(options: Options) ResolveError!Config { | ... | @@ -435,7 +436,13 @@ pub fn resolve(options: Options) ResolveError!Config { |
| 435 | } | 436 | } |
| 436 | 437 | ||
| 437 | if (options.use_lld) |x| break :b x; | 438 | if (options.use_lld) |x| break :b x; |
| 438 | break :b prefer_llvm; | 439 | |
| 440 | // If we have no zig code to compile, no need for the self-hosted linker. | ||
| 441 | if (!options.have_zcu) break :b true; | ||
| 442 | |||
| 443 | // If we do have zig code, match the decision for whether to use the llvm backend, | ||
| 444 | // so that the llvm backend defaults to lld and the self-hosted backends do not. | ||
| 445 | break :b use_llvm; | ||
| 439 | }; | 446 | }; |
| 440 | 447 | ||
| 441 | const lto: std.zig.LtoMode = b: { | 448 | const lto: std.zig.LtoMode = b: { |
src/InternPool.zig+71-49| ... | @@ -526,10 +526,10 @@ pub const Nav = struct { | ... | @@ -526,10 +526,10 @@ pub const Nav = struct { |
| 526 | /// The type of this `Nav` is resolved; the value is queued for resolution. | 526 | /// The type of this `Nav` is resolved; the value is queued for resolution. |
| 527 | type_resolved: struct { | 527 | type_resolved: struct { |
| 528 | type: InternPool.Index, | 528 | type: InternPool.Index, |
| 529 | is_const: bool, | ||
| 529 | alignment: Alignment, | 530 | alignment: Alignment, |
| 530 | @"linksection": OptionalNullTerminatedString, | 531 | @"linksection": OptionalNullTerminatedString, |
| 531 | @"addrspace": std.builtin.AddressSpace, | 532 | @"addrspace": std.builtin.AddressSpace, |
| 532 | is_const: bool, | ||
| 533 | is_threadlocal: bool, | 533 | is_threadlocal: bool, |
| 534 | /// This field is whether this `Nav` is a literal `extern` definition. | 534 | /// This field is whether this `Nav` is a literal `extern` definition. |
| 535 | /// It does *not* tell you whether this might alias an extern fn (see #21027). | 535 | /// It does *not* tell you whether this might alias an extern fn (see #21027). |
| ... | @@ -538,6 +538,7 @@ pub const Nav = struct { | ... | @@ -538,6 +538,7 @@ pub const Nav = struct { |
| 538 | /// The value of this `Nav` is resolved. | 538 | /// The value of this `Nav` is resolved. |
| 539 | fully_resolved: struct { | 539 | fully_resolved: struct { |
| 540 | val: InternPool.Index, | 540 | val: InternPool.Index, |
| 541 | is_const: bool, | ||
| 541 | alignment: Alignment, | 542 | alignment: Alignment, |
| 542 | @"linksection": OptionalNullTerminatedString, | 543 | @"linksection": OptionalNullTerminatedString, |
| 543 | @"addrspace": std.builtin.AddressSpace, | 544 | @"addrspace": std.builtin.AddressSpace, |
| ... | @@ -727,12 +728,12 @@ pub const Nav = struct { | ... | @@ -727,12 +728,12 @@ pub const Nav = struct { |
| 727 | const Bits = packed struct(u16) { | 728 | const Bits = packed struct(u16) { |
| 728 | status: enum(u2) { unresolved, type_resolved, fully_resolved, type_resolved_extern_decl }, | 729 | status: enum(u2) { unresolved, type_resolved, fully_resolved, type_resolved_extern_decl }, |
| 729 | /// Populated only if `bits.status != .unresolved`. | 730 | /// Populated only if `bits.status != .unresolved`. |
| 731 | is_const: bool, | ||
| 732 | /// Populated only if `bits.status != .unresolved`. | ||
| 730 | alignment: Alignment, | 733 | alignment: Alignment, |
| 731 | /// Populated only if `bits.status != .unresolved`. | 734 | /// Populated only if `bits.status != .unresolved`. |
| 732 | @"addrspace": std.builtin.AddressSpace, | 735 | @"addrspace": std.builtin.AddressSpace, |
| 733 | /// Populated only if `bits.status == .type_resolved`. | 736 | /// Populated only if `bits.status == .type_resolved`. |
| 734 | is_const: bool, | ||
| 735 | /// Populated only if `bits.status == .type_resolved`. | ||
| 736 | is_threadlocal: bool, | 737 | is_threadlocal: bool, |
| 737 | is_usingnamespace: bool, | 738 | is_usingnamespace: bool, |
| 738 | }; | 739 | }; |
| ... | @@ -753,15 +754,16 @@ pub const Nav = struct { | ... | @@ -753,15 +754,16 @@ pub const Nav = struct { |
| 753 | .unresolved => .unresolved, | 754 | .unresolved => .unresolved, |
| 754 | .type_resolved, .type_resolved_extern_decl => .{ .type_resolved = .{ | 755 | .type_resolved, .type_resolved_extern_decl => .{ .type_resolved = .{ |
| 755 | .type = repr.type_or_val, | 756 | .type = repr.type_or_val, |
| 757 | .is_const = repr.bits.is_const, | ||
| 756 | .alignment = repr.bits.alignment, | 758 | .alignment = repr.bits.alignment, |
| 757 | .@"linksection" = repr.@"linksection", | 759 | .@"linksection" = repr.@"linksection", |
| 758 | .@"addrspace" = repr.bits.@"addrspace", | 760 | .@"addrspace" = repr.bits.@"addrspace", |
| 759 | .is_const = repr.bits.is_const, | ||
| 760 | .is_threadlocal = repr.bits.is_threadlocal, | 761 | .is_threadlocal = repr.bits.is_threadlocal, |
| 761 | .is_extern_decl = repr.bits.status == .type_resolved_extern_decl, | 762 | .is_extern_decl = repr.bits.status == .type_resolved_extern_decl, |
| 762 | } }, | 763 | } }, |
| 763 | .fully_resolved => .{ .fully_resolved = .{ | 764 | .fully_resolved => .{ .fully_resolved = .{ |
| 764 | .val = repr.type_or_val, | 765 | .val = repr.type_or_val, |
| 766 | .is_const = repr.bits.is_const, | ||
| 765 | .alignment = repr.bits.alignment, | 767 | .alignment = repr.bits.alignment, |
| 766 | .@"linksection" = repr.@"linksection", | 768 | .@"linksection" = repr.@"linksection", |
| 767 | .@"addrspace" = repr.bits.@"addrspace", | 769 | .@"addrspace" = repr.bits.@"addrspace", |
| ... | @@ -792,26 +794,26 @@ pub const Nav = struct { | ... | @@ -792,26 +794,26 @@ pub const Nav = struct { |
| 792 | .bits = switch (nav.status) { | 794 | .bits = switch (nav.status) { |
| 793 | .unresolved => .{ | 795 | .unresolved => .{ |
| 794 | .status = .unresolved, | 796 | .status = .unresolved, |
| 797 | .is_const = false, | ||
| 795 | .alignment = .none, | 798 | .alignment = .none, |
| 796 | .@"addrspace" = .generic, | 799 | .@"addrspace" = .generic, |
| 797 | .is_usingnamespace = nav.is_usingnamespace, | 800 | .is_usingnamespace = nav.is_usingnamespace, |
| 798 | .is_const = false, | ||
| 799 | .is_threadlocal = false, | 801 | .is_threadlocal = false, |
| 800 | }, | 802 | }, |
| 801 | .type_resolved => |r| .{ | 803 | .type_resolved => |r| .{ |
| 802 | .status = if (r.is_extern_decl) .type_resolved_extern_decl else .type_resolved, | 804 | .status = if (r.is_extern_decl) .type_resolved_extern_decl else .type_resolved, |
| 805 | .is_const = r.is_const, | ||
| 803 | .alignment = r.alignment, | 806 | .alignment = r.alignment, |
| 804 | .@"addrspace" = r.@"addrspace", | 807 | .@"addrspace" = r.@"addrspace", |
| 805 | .is_usingnamespace = nav.is_usingnamespace, | 808 | .is_usingnamespace = nav.is_usingnamespace, |
| 806 | .is_const = r.is_const, | ||
| 807 | .is_threadlocal = r.is_threadlocal, | 809 | .is_threadlocal = r.is_threadlocal, |
| 808 | }, | 810 | }, |
| 809 | .fully_resolved => |r| .{ | 811 | .fully_resolved => |r| .{ |
| 810 | .status = .fully_resolved, | 812 | .status = .fully_resolved, |
| 813 | .is_const = r.is_const, | ||
| 811 | .alignment = r.alignment, | 814 | .alignment = r.alignment, |
| 812 | .@"addrspace" = r.@"addrspace", | 815 | .@"addrspace" = r.@"addrspace", |
| 813 | .is_usingnamespace = nav.is_usingnamespace, | 816 | .is_usingnamespace = nav.is_usingnamespace, |
| 814 | .is_const = false, | ||
| 815 | .is_threadlocal = false, | 817 | .is_threadlocal = false, |
| 816 | }, | 818 | }, |
| 817 | }, | 819 | }, |
| ... | @@ -2221,7 +2223,6 @@ pub const Key = union(enum) { | ... | @@ -2221,7 +2223,6 @@ pub const Key = union(enum) { |
| 2221 | init: Index, | 2223 | init: Index, |
| 2222 | owner_nav: Nav.Index, | 2224 | owner_nav: Nav.Index, |
| 2223 | is_threadlocal: bool, | 2225 | is_threadlocal: bool, |
| 2224 | is_weak_linkage: bool, | ||
| 2225 | }; | 2226 | }; |
| 2226 | 2227 | ||
| 2227 | pub const Extern = struct { | 2228 | pub const Extern = struct { |
| ... | @@ -2234,10 +2235,12 @@ pub const Key = union(enum) { | ... | @@ -2234,10 +2235,12 @@ pub const Key = union(enum) { |
| 2234 | /// For example `extern "c" fn write(...) usize` would have 'c' as library name. | 2235 | /// For example `extern "c" fn write(...) usize` would have 'c' as library name. |
| 2235 | /// Index into the string table bytes. | 2236 | /// Index into the string table bytes. |
| 2236 | lib_name: OptionalNullTerminatedString, | 2237 | lib_name: OptionalNullTerminatedString, |
| 2237 | is_const: bool, | 2238 | linkage: std.builtin.GlobalLinkage, |
| 2239 | visibility: std.builtin.SymbolVisibility, | ||
| 2238 | is_threadlocal: bool, | 2240 | is_threadlocal: bool, |
| 2239 | is_weak_linkage: bool, | ||
| 2240 | is_dll_import: bool, | 2241 | is_dll_import: bool, |
| 2242 | relocation: std.builtin.ExternOptions.Relocation, | ||
| 2243 | is_const: bool, | ||
| 2241 | alignment: Alignment, | 2244 | alignment: Alignment, |
| 2242 | @"addrspace": std.builtin.AddressSpace, | 2245 | @"addrspace": std.builtin.AddressSpace, |
| 2243 | /// The ZIR instruction which created this extern; used only for source locations. | 2246 | /// The ZIR instruction which created this extern; used only for source locations. |
| ... | @@ -2844,9 +2847,10 @@ pub const Key = union(enum) { | ... | @@ -2844,9 +2847,10 @@ pub const Key = union(enum) { |
| 2844 | 2847 | ||
| 2845 | .@"extern" => |e| Hash.hash(seed, asBytes(&e.name) ++ | 2848 | .@"extern" => |e| Hash.hash(seed, asBytes(&e.name) ++ |
| 2846 | asBytes(&e.ty) ++ asBytes(&e.lib_name) ++ | 2849 | asBytes(&e.ty) ++ asBytes(&e.lib_name) ++ |
| 2847 | asBytes(&e.is_const) ++ asBytes(&e.is_threadlocal) ++ | 2850 | asBytes(&e.linkage) ++ asBytes(&e.visibility) ++ |
| 2848 | asBytes(&e.is_weak_linkage) ++ asBytes(&e.alignment) ++ | 2851 | asBytes(&e.is_threadlocal) ++ asBytes(&e.is_dll_import) ++ |
| 2849 | asBytes(&e.is_dll_import) ++ asBytes(&e.@"addrspace") ++ | 2852 | asBytes(&e.relocation) ++ |
| 2853 | asBytes(&e.is_const) ++ asBytes(&e.alignment) ++ asBytes(&e.@"addrspace") ++ | ||
| 2850 | asBytes(&e.zir_index)), | 2854 | asBytes(&e.zir_index)), |
| 2851 | }; | 2855 | }; |
| 2852 | } | 2856 | } |
| ... | @@ -2928,21 +2932,22 @@ pub const Key = union(enum) { | ... | @@ -2928,21 +2932,22 @@ pub const Key = union(enum) { |
| 2928 | 2932 | ||
| 2929 | .variable => |a_info| { | 2933 | .variable => |a_info| { |
| 2930 | const b_info = b.variable; | 2934 | const b_info = b.variable; |
| 2931 | return a_info.owner_nav == b_info.owner_nav and | 2935 | return a_info.ty == b_info.ty and |
| 2932 | a_info.ty == b_info.ty and | ||
| 2933 | a_info.init == b_info.init and | 2936 | a_info.init == b_info.init and |
| 2934 | a_info.is_threadlocal == b_info.is_threadlocal and | 2937 | a_info.owner_nav == b_info.owner_nav and |
| 2935 | a_info.is_weak_linkage == b_info.is_weak_linkage; | 2938 | a_info.is_threadlocal == b_info.is_threadlocal; |
| 2936 | }, | 2939 | }, |
| 2937 | .@"extern" => |a_info| { | 2940 | .@"extern" => |a_info| { |
| 2938 | const b_info = b.@"extern"; | 2941 | const b_info = b.@"extern"; |
| 2939 | return a_info.name == b_info.name and | 2942 | return a_info.name == b_info.name and |
| 2940 | a_info.ty == b_info.ty and | 2943 | a_info.ty == b_info.ty and |
| 2941 | a_info.lib_name == b_info.lib_name and | 2944 | a_info.lib_name == b_info.lib_name and |
| 2942 | a_info.is_const == b_info.is_const and | 2945 | a_info.linkage == b_info.linkage and |
| 2946 | a_info.visibility == b_info.visibility and | ||
| 2943 | a_info.is_threadlocal == b_info.is_threadlocal and | 2947 | a_info.is_threadlocal == b_info.is_threadlocal and |
| 2944 | a_info.is_weak_linkage == b_info.is_weak_linkage and | ||
| 2945 | a_info.is_dll_import == b_info.is_dll_import and | 2948 | a_info.is_dll_import == b_info.is_dll_import and |
| 2949 | a_info.relocation == b_info.relocation and | ||
| 2950 | a_info.is_const == b_info.is_const and | ||
| 2946 | a_info.alignment == b_info.alignment and | 2951 | a_info.alignment == b_info.alignment and |
| 2947 | a_info.@"addrspace" == b_info.@"addrspace" and | 2952 | a_info.@"addrspace" == b_info.@"addrspace" and |
| 2948 | a_info.zir_index == b_info.zir_index; | 2953 | a_info.zir_index == b_info.zir_index; |
| ... | @@ -4889,6 +4894,7 @@ pub const Index = enum(u32) { | ... | @@ -4889,6 +4894,7 @@ pub const Index = enum(u32) { |
| 4889 | float_c_longdouble_f128: struct { data: *Float128 }, | 4894 | float_c_longdouble_f128: struct { data: *Float128 }, |
| 4890 | float_comptime_float: struct { data: *Float128 }, | 4895 | float_comptime_float: struct { data: *Float128 }, |
| 4891 | variable: struct { data: *Tag.Variable }, | 4896 | variable: struct { data: *Tag.Variable }, |
| 4897 | threadlocal_variable: struct { data: *Tag.Variable }, | ||
| 4892 | @"extern": struct { data: *Tag.Extern }, | 4898 | @"extern": struct { data: *Tag.Extern }, |
| 4893 | func_decl: struct { | 4899 | func_decl: struct { |
| 4894 | const @"data.analysis.inferred_error_set" = opaque {}; | 4900 | const @"data.analysis.inferred_error_set" = opaque {}; |
| ... | @@ -5548,6 +5554,9 @@ pub const Tag = enum(u8) { | ... | @@ -5548,6 +5554,9 @@ pub const Tag = enum(u8) { |
| 5548 | /// A global variable. | 5554 | /// A global variable. |
| 5549 | /// data is extra index to Variable. | 5555 | /// data is extra index to Variable. |
| 5550 | variable, | 5556 | variable, |
| 5557 | /// A global threadlocal variable. | ||
| 5558 | /// data is extra index to Variable. | ||
| 5559 | threadlocal_variable, | ||
| 5551 | /// An extern function or variable. | 5560 | /// An extern function or variable. |
| 5552 | /// data is extra index to Extern. | 5561 | /// data is extra index to Extern. |
| 5553 | /// Some parts of the key are stored in `owner_nav`. | 5562 | /// Some parts of the key are stored in `owner_nav`. |
| ... | @@ -5863,6 +5872,7 @@ pub const Tag = enum(u8) { | ... | @@ -5863,6 +5872,7 @@ pub const Tag = enum(u8) { |
| 5863 | .float_c_longdouble_f128 = .{ .summary = .@"@as(c_longdouble, {.payload%value})", .payload = f128 }, | 5872 | .float_c_longdouble_f128 = .{ .summary = .@"@as(c_longdouble, {.payload%value})", .payload = f128 }, |
| 5864 | .float_comptime_float = .{ .summary = .@"{.payload%value}", .payload = f128 }, | 5873 | .float_comptime_float = .{ .summary = .@"{.payload%value}", .payload = f128 }, |
| 5865 | .variable = .{ .summary = .@"{.payload.owner_nav.fqn%summary#\"}", .payload = Variable }, | 5874 | .variable = .{ .summary = .@"{.payload.owner_nav.fqn%summary#\"}", .payload = Variable }, |
| 5875 | .threadlocal_variable = .{ .summary = .@"{.payload.owner_nav.fqn%summary#\"}", .payload = Variable }, | ||
| 5866 | .@"extern" = .{ .summary = .@"{.payload.owner_nav.fqn%summary#\"}", .payload = Extern }, | 5876 | .@"extern" = .{ .summary = .@"{.payload.owner_nav.fqn%summary#\"}", .payload = Extern }, |
| 5867 | .func_decl = .{ | 5877 | .func_decl = .{ |
| 5868 | .summary = .@"{.payload.owner_nav.fqn%summary#\"}", | 5878 | .summary = .@"{.payload.owner_nav.fqn%summary#\"}", |
| ... | @@ -5913,24 +5923,24 @@ pub const Tag = enum(u8) { | ... | @@ -5913,24 +5923,24 @@ pub const Tag = enum(u8) { |
| 5913 | /// May be `none`. | 5923 | /// May be `none`. |
| 5914 | init: Index, | 5924 | init: Index, |
| 5915 | owner_nav: Nav.Index, | 5925 | owner_nav: Nav.Index, |
| 5916 | flags: Flags, | ||
| 5917 | |||
| 5918 | pub const Flags = packed struct(u32) { | ||
| 5919 | is_const: bool, | ||
| 5920 | is_threadlocal: bool, | ||
| 5921 | is_weak_linkage: bool, | ||
| 5922 | is_dll_import: bool, | ||
| 5923 | _: u28 = 0, | ||
| 5924 | }; | ||
| 5925 | }; | 5926 | }; |
| 5926 | 5927 | ||
| 5927 | pub const Extern = struct { | 5928 | pub const Extern = struct { |
| 5928 | // name, alignment, addrspace come from `owner_nav`. | 5929 | // name, is_const, alignment, addrspace come from `owner_nav`. |
| 5929 | ty: Index, | 5930 | ty: Index, |
| 5930 | lib_name: OptionalNullTerminatedString, | 5931 | lib_name: OptionalNullTerminatedString, |
| 5931 | flags: Variable.Flags, | 5932 | flags: Flags, |
| 5932 | owner_nav: Nav.Index, | 5933 | owner_nav: Nav.Index, |
| 5933 | zir_index: TrackedInst.Index, | 5934 | zir_index: TrackedInst.Index, |
| 5935 | |||
| 5936 | pub const Flags = packed struct(u32) { | ||
| 5937 | linkage: std.builtin.GlobalLinkage, | ||
| 5938 | visibility: std.builtin.SymbolVisibility, | ||
| 5939 | is_threadlocal: bool, | ||
| 5940 | is_dll_import: bool, | ||
| 5941 | relocation: std.builtin.ExternOptions.Relocation, | ||
| 5942 | _: u25 = 0, | ||
| 5943 | }; | ||
| 5934 | }; | 5944 | }; |
| 5935 | 5945 | ||
| 5936 | /// Trailing: | 5946 | /// Trailing: |
| ... | @@ -7248,14 +7258,17 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { | ... | @@ -7248,14 +7258,17 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { |
| 7248 | .ty = .comptime_float_type, | 7258 | .ty = .comptime_float_type, |
| 7249 | .storage = .{ .f128 = extraData(unwrapped_index.getExtra(ip), Float128, data).get() }, | 7259 | .storage = .{ .f128 = extraData(unwrapped_index.getExtra(ip), Float128, data).get() }, |
| 7250 | } }, | 7260 | } }, |
| 7251 | .variable => { | 7261 | .variable, .threadlocal_variable => { |
| 7252 | const extra = extraData(unwrapped_index.getExtra(ip), Tag.Variable, data); | 7262 | const extra = extraData(unwrapped_index.getExtra(ip), Tag.Variable, data); |
| 7253 | return .{ .variable = .{ | 7263 | return .{ .variable = .{ |
| 7254 | .ty = extra.ty, | 7264 | .ty = extra.ty, |
| 7255 | .init = extra.init, | 7265 | .init = extra.init, |
| 7256 | .owner_nav = extra.owner_nav, | 7266 | .owner_nav = extra.owner_nav, |
| 7257 | .is_threadlocal = extra.flags.is_threadlocal, | 7267 | .is_threadlocal = switch (item.tag) { |
| 7258 | .is_weak_linkage = extra.flags.is_weak_linkage, | 7268 | else => unreachable, |
| 7269 | .variable => false, | ||
| 7270 | .threadlocal_variable => true, | ||
| 7271 | }, | ||
| 7259 | } }; | 7272 | } }; |
| 7260 | }, | 7273 | }, |
| 7261 | .@"extern" => { | 7274 | .@"extern" => { |
| ... | @@ -7265,10 +7278,12 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { | ... | @@ -7265,10 +7278,12 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { |
| 7265 | .name = nav.name, | 7278 | .name = nav.name, |
| 7266 | .ty = extra.ty, | 7279 | .ty = extra.ty, |
| 7267 | .lib_name = extra.lib_name, | 7280 | .lib_name = extra.lib_name, |
| 7268 | .is_const = extra.flags.is_const, | 7281 | .linkage = extra.flags.linkage, |
| 7282 | .visibility = extra.flags.visibility, | ||
| 7269 | .is_threadlocal = extra.flags.is_threadlocal, | 7283 | .is_threadlocal = extra.flags.is_threadlocal, |
| 7270 | .is_weak_linkage = extra.flags.is_weak_linkage, | ||
| 7271 | .is_dll_import = extra.flags.is_dll_import, | 7284 | .is_dll_import = extra.flags.is_dll_import, |
| 7285 | .relocation = extra.flags.relocation, | ||
| 7286 | .is_const = nav.status.fully_resolved.is_const, | ||
| 7272 | .alignment = nav.status.fully_resolved.alignment, | 7287 | .alignment = nav.status.fully_resolved.alignment, |
| 7273 | .@"addrspace" = nav.status.fully_resolved.@"addrspace", | 7288 | .@"addrspace" = nav.status.fully_resolved.@"addrspace", |
| 7274 | .zir_index = extra.zir_index, | 7289 | .zir_index = extra.zir_index, |
| ... | @@ -7895,17 +7910,14 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All | ... | @@ -7895,17 +7910,14 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All |
| 7895 | const has_init = variable.init != .none; | 7910 | const has_init = variable.init != .none; |
| 7896 | if (has_init) assert(variable.ty == ip.typeOf(variable.init)); | 7911 | if (has_init) assert(variable.ty == ip.typeOf(variable.init)); |
| 7897 | items.appendAssumeCapacity(.{ | 7912 | items.appendAssumeCapacity(.{ |
| 7898 | .tag = .variable, | 7913 | .tag = switch (variable.is_threadlocal) { |
| 7914 | false => .variable, | ||
| 7915 | true => .threadlocal_variable, | ||
| 7916 | }, | ||
| 7899 | .data = try addExtra(extra, Tag.Variable{ | 7917 | .data = try addExtra(extra, Tag.Variable{ |
| 7900 | .ty = variable.ty, | 7918 | .ty = variable.ty, |
| 7901 | .init = variable.init, | 7919 | .init = variable.init, |
| 7902 | .owner_nav = variable.owner_nav, | 7920 | .owner_nav = variable.owner_nav, |
| 7903 | .flags = .{ | ||
| 7904 | .is_const = false, | ||
| 7905 | .is_threadlocal = variable.is_threadlocal, | ||
| 7906 | .is_weak_linkage = variable.is_weak_linkage, | ||
| 7907 | .is_dll_import = false, | ||
| 7908 | }, | ||
| 7909 | }), | 7921 | }), |
| 7910 | }); | 7922 | }); |
| 7911 | }, | 7923 | }, |
| ... | @@ -9128,6 +9140,7 @@ pub fn getExtern( | ... | @@ -9128,6 +9140,7 @@ pub fn getExtern( |
| 9128 | .name = key.name, | 9140 | .name = key.name, |
| 9129 | .fqn = key.name, | 9141 | .fqn = key.name, |
| 9130 | .val = extern_index, | 9142 | .val = extern_index, |
| 9143 | .is_const = key.is_const, | ||
| 9131 | .alignment = key.alignment, | 9144 | .alignment = key.alignment, |
| 9132 | .@"linksection" = .none, | 9145 | .@"linksection" = .none, |
| 9133 | .@"addrspace" = key.@"addrspace", | 9146 | .@"addrspace" = key.@"addrspace", |
| ... | @@ -9136,10 +9149,11 @@ pub fn getExtern( | ... | @@ -9136,10 +9149,11 @@ pub fn getExtern( |
| 9136 | .ty = key.ty, | 9149 | .ty = key.ty, |
| 9137 | .lib_name = key.lib_name, | 9150 | .lib_name = key.lib_name, |
| 9138 | .flags = .{ | 9151 | .flags = .{ |
| 9139 | .is_const = key.is_const, | 9152 | .linkage = key.linkage, |
| 9153 | .visibility = key.visibility, | ||
| 9140 | .is_threadlocal = key.is_threadlocal, | 9154 | .is_threadlocal = key.is_threadlocal, |
| 9141 | .is_weak_linkage = key.is_weak_linkage, | ||
| 9142 | .is_dll_import = key.is_dll_import, | 9155 | .is_dll_import = key.is_dll_import, |
| 9156 | .relocation = key.relocation, | ||
| 9143 | }, | 9157 | }, |
| 9144 | .zir_index = key.zir_index, | 9158 | .zir_index = key.zir_index, |
| 9145 | .owner_nav = owner_nav, | 9159 | .owner_nav = owner_nav, |
| ... | @@ -9714,6 +9728,7 @@ fn finishFuncInstance( | ... | @@ -9714,6 +9728,7 @@ fn finishFuncInstance( |
| 9714 | .name = nav_name, | 9728 | .name = nav_name, |
| 9715 | .fqn = try ip.namespacePtr(fn_namespace).internFullyQualifiedName(ip, gpa, tid, nav_name), | 9729 | .fqn = try ip.namespacePtr(fn_namespace).internFullyQualifiedName(ip, gpa, tid, nav_name), |
| 9716 | .val = func_index, | 9730 | .val = func_index, |
| 9731 | .is_const = fn_owner_nav.status.fully_resolved.is_const, | ||
| 9717 | .alignment = fn_owner_nav.status.fully_resolved.alignment, | 9732 | .alignment = fn_owner_nav.status.fully_resolved.alignment, |
| 9718 | .@"linksection" = fn_owner_nav.status.fully_resolved.@"linksection", | 9733 | .@"linksection" = fn_owner_nav.status.fully_resolved.@"linksection", |
| 9719 | .@"addrspace" = fn_owner_nav.status.fully_resolved.@"addrspace", | 9734 | .@"addrspace" = fn_owner_nav.status.fully_resolved.@"addrspace", |
| ... | @@ -10300,13 +10315,13 @@ fn addExtraAssumeCapacity(extra: Local.Extra.Mutable, item: anytype) u32 { | ... | @@ -10300,13 +10315,13 @@ fn addExtraAssumeCapacity(extra: Local.Extra.Mutable, item: anytype) u32 { |
| 10300 | u32, | 10315 | u32, |
| 10301 | i32, | 10316 | i32, |
| 10302 | FuncAnalysis, | 10317 | FuncAnalysis, |
| 10318 | Tag.Extern.Flags, | ||
| 10303 | Tag.TypePointer.Flags, | 10319 | Tag.TypePointer.Flags, |
| 10304 | Tag.TypeFunction.Flags, | 10320 | Tag.TypeFunction.Flags, |
| 10305 | Tag.TypePointer.PackedOffset, | 10321 | Tag.TypePointer.PackedOffset, |
| 10306 | Tag.TypeUnion.Flags, | 10322 | Tag.TypeUnion.Flags, |
| 10307 | Tag.TypeStruct.Flags, | 10323 | Tag.TypeStruct.Flags, |
| 10308 | Tag.TypeStructPacked.Flags, | 10324 | Tag.TypeStructPacked.Flags, |
| 10309 | Tag.Variable.Flags, | ||
| 10310 | => @bitCast(@field(item, field.name)), | 10325 | => @bitCast(@field(item, field.name)), |
| 10311 | 10326 | ||
| 10312 | else => @compileError("bad field type: " ++ @typeName(field.type)), | 10327 | else => @compileError("bad field type: " ++ @typeName(field.type)), |
| ... | @@ -10361,13 +10376,13 @@ fn extraDataTrail(extra: Local.Extra, comptime T: type, index: u32) struct { dat | ... | @@ -10361,13 +10376,13 @@ fn extraDataTrail(extra: Local.Extra, comptime T: type, index: u32) struct { dat |
| 10361 | 10376 | ||
| 10362 | u32, | 10377 | u32, |
| 10363 | i32, | 10378 | i32, |
| 10379 | Tag.Extern.Flags, | ||
| 10364 | Tag.TypePointer.Flags, | 10380 | Tag.TypePointer.Flags, |
| 10365 | Tag.TypeFunction.Flags, | 10381 | Tag.TypeFunction.Flags, |
| 10366 | Tag.TypePointer.PackedOffset, | 10382 | Tag.TypePointer.PackedOffset, |
| 10367 | Tag.TypeUnion.Flags, | 10383 | Tag.TypeUnion.Flags, |
| 10368 | Tag.TypeStruct.Flags, | 10384 | Tag.TypeStruct.Flags, |
| 10369 | Tag.TypeStructPacked.Flags, | 10385 | Tag.TypeStructPacked.Flags, |
| 10370 | Tag.Variable.Flags, | ||
| 10371 | FuncAnalysis, | 10386 | FuncAnalysis, |
| 10372 | => @bitCast(extra_item), | 10387 | => @bitCast(extra_item), |
| 10373 | 10388 | ||
| ... | @@ -11162,7 +11177,7 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void { | ... | @@ -11162,7 +11177,7 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void { |
| 11162 | .float_c_longdouble_f80 => @sizeOf(Float80), | 11177 | .float_c_longdouble_f80 => @sizeOf(Float80), |
| 11163 | .float_c_longdouble_f128 => @sizeOf(Float128), | 11178 | .float_c_longdouble_f128 => @sizeOf(Float128), |
| 11164 | .float_comptime_float => @sizeOf(Float128), | 11179 | .float_comptime_float => @sizeOf(Float128), |
| 11165 | .variable => @sizeOf(Tag.Variable), | 11180 | .variable, .threadlocal_variable => @sizeOf(Tag.Variable), |
| 11166 | .@"extern" => @sizeOf(Tag.Extern), | 11181 | .@"extern" => @sizeOf(Tag.Extern), |
| 11167 | .func_decl => @sizeOf(Tag.FuncDecl), | 11182 | .func_decl => @sizeOf(Tag.FuncDecl), |
| 11168 | .func_instance => b: { | 11183 | .func_instance => b: { |
| ... | @@ -11282,6 +11297,7 @@ fn dumpAllFallible(ip: *const InternPool) anyerror!void { | ... | @@ -11282,6 +11297,7 @@ fn dumpAllFallible(ip: *const InternPool) anyerror!void { |
| 11282 | .float_c_longdouble_f128, | 11297 | .float_c_longdouble_f128, |
| 11283 | .float_comptime_float, | 11298 | .float_comptime_float, |
| 11284 | .variable, | 11299 | .variable, |
| 11300 | .threadlocal_variable, | ||
| 11285 | .@"extern", | 11301 | .@"extern", |
| 11286 | .func_decl, | 11302 | .func_decl, |
| 11287 | .func_instance, | 11303 | .func_instance, |
| ... | @@ -11414,6 +11430,7 @@ pub fn createNav( | ... | @@ -11414,6 +11430,7 @@ pub fn createNav( |
| 11414 | name: NullTerminatedString, | 11430 | name: NullTerminatedString, |
| 11415 | fqn: NullTerminatedString, | 11431 | fqn: NullTerminatedString, |
| 11416 | val: InternPool.Index, | 11432 | val: InternPool.Index, |
| 11433 | is_const: bool, | ||
| 11417 | alignment: Alignment, | 11434 | alignment: Alignment, |
| 11418 | @"linksection": OptionalNullTerminatedString, | 11435 | @"linksection": OptionalNullTerminatedString, |
| 11419 | @"addrspace": std.builtin.AddressSpace, | 11436 | @"addrspace": std.builtin.AddressSpace, |
| ... | @@ -11430,6 +11447,7 @@ pub fn createNav( | ... | @@ -11430,6 +11447,7 @@ pub fn createNav( |
| 11430 | .analysis = null, | 11447 | .analysis = null, |
| 11431 | .status = .{ .fully_resolved = .{ | 11448 | .status = .{ .fully_resolved = .{ |
| 11432 | .val = opts.val, | 11449 | .val = opts.val, |
| 11450 | .is_const = opts.is_const, | ||
| 11433 | .alignment = opts.alignment, | 11451 | .alignment = opts.alignment, |
| 11434 | .@"linksection" = opts.@"linksection", | 11452 | .@"linksection" = opts.@"linksection", |
| 11435 | .@"addrspace" = opts.@"addrspace", | 11453 | .@"addrspace" = opts.@"addrspace", |
| ... | @@ -11482,10 +11500,10 @@ pub fn resolveNavType( | ... | @@ -11482,10 +11500,10 @@ pub fn resolveNavType( |
| 11482 | nav: Nav.Index, | 11500 | nav: Nav.Index, |
| 11483 | resolved: struct { | 11501 | resolved: struct { |
| 11484 | type: InternPool.Index, | 11502 | type: InternPool.Index, |
| 11503 | is_const: bool, | ||
| 11485 | alignment: Alignment, | 11504 | alignment: Alignment, |
| 11486 | @"linksection": OptionalNullTerminatedString, | 11505 | @"linksection": OptionalNullTerminatedString, |
| 11487 | @"addrspace": std.builtin.AddressSpace, | 11506 | @"addrspace": std.builtin.AddressSpace, |
| 11488 | is_const: bool, | ||
| 11489 | is_threadlocal: bool, | 11507 | is_threadlocal: bool, |
| 11490 | is_extern_decl: bool, | 11508 | is_extern_decl: bool, |
| 11491 | }, | 11509 | }, |
| ... | @@ -11512,9 +11530,9 @@ pub fn resolveNavType( | ... | @@ -11512,9 +11530,9 @@ pub fn resolveNavType( |
| 11512 | 11530 | ||
| 11513 | var bits = nav_bits[unwrapped.index]; | 11531 | var bits = nav_bits[unwrapped.index]; |
| 11514 | bits.status = if (resolved.is_extern_decl) .type_resolved_extern_decl else .type_resolved; | 11532 | bits.status = if (resolved.is_extern_decl) .type_resolved_extern_decl else .type_resolved; |
| 11533 | bits.is_const = resolved.is_const; | ||
| 11515 | bits.alignment = resolved.alignment; | 11534 | bits.alignment = resolved.alignment; |
| 11516 | bits.@"addrspace" = resolved.@"addrspace"; | 11535 | bits.@"addrspace" = resolved.@"addrspace"; |
| 11517 | bits.is_const = resolved.is_const; | ||
| 11518 | bits.is_threadlocal = resolved.is_threadlocal; | 11536 | bits.is_threadlocal = resolved.is_threadlocal; |
| 11519 | @atomicStore(Nav.Repr.Bits, &nav_bits[unwrapped.index], bits, .release); | 11537 | @atomicStore(Nav.Repr.Bits, &nav_bits[unwrapped.index], bits, .release); |
| 11520 | } | 11538 | } |
| ... | @@ -11526,6 +11544,7 @@ pub fn resolveNavValue( | ... | @@ -11526,6 +11544,7 @@ pub fn resolveNavValue( |
| 11526 | nav: Nav.Index, | 11544 | nav: Nav.Index, |
| 11527 | resolved: struct { | 11545 | resolved: struct { |
| 11528 | val: InternPool.Index, | 11546 | val: InternPool.Index, |
| 11547 | is_const: bool, | ||
| 11529 | alignment: Alignment, | 11548 | alignment: Alignment, |
| 11530 | @"linksection": OptionalNullTerminatedString, | 11549 | @"linksection": OptionalNullTerminatedString, |
| 11531 | @"addrspace": std.builtin.AddressSpace, | 11550 | @"addrspace": std.builtin.AddressSpace, |
| ... | @@ -11553,6 +11572,7 @@ pub fn resolveNavValue( | ... | @@ -11553,6 +11572,7 @@ pub fn resolveNavValue( |
| 11553 | 11572 | ||
| 11554 | var bits = nav_bits[unwrapped.index]; | 11573 | var bits = nav_bits[unwrapped.index]; |
| 11555 | bits.status = .fully_resolved; | 11574 | bits.status = .fully_resolved; |
| 11575 | bits.is_const = resolved.is_const; | ||
| 11556 | bits.alignment = resolved.alignment; | 11576 | bits.alignment = resolved.alignment; |
| 11557 | bits.@"addrspace" = resolved.@"addrspace"; | 11577 | bits.@"addrspace" = resolved.@"addrspace"; |
| 11558 | @atomicStore(Nav.Repr.Bits, &nav_bits[unwrapped.index], bits, .release); | 11578 | @atomicStore(Nav.Repr.Bits, &nav_bits[unwrapped.index], bits, .release); |
| ... | @@ -12007,6 +12027,7 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index { | ... | @@ -12007,6 +12027,7 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index { |
| 12007 | .error_union_error, | 12027 | .error_union_error, |
| 12008 | .enum_tag, | 12028 | .enum_tag, |
| 12009 | .variable, | 12029 | .variable, |
| 12030 | .threadlocal_variable, | ||
| 12010 | .@"extern", | 12031 | .@"extern", |
| 12011 | .func_decl, | 12032 | .func_decl, |
| 12012 | .func_instance, | 12033 | .func_instance, |
| ... | @@ -12391,6 +12412,7 @@ pub fn zigTypeTag(ip: *const InternPool, index: Index) std.builtin.TypeId { | ... | @@ -12391,6 +12412,7 @@ pub fn zigTypeTag(ip: *const InternPool, index: Index) std.builtin.TypeId { |
| 12391 | .float_c_longdouble_f128, | 12412 | .float_c_longdouble_f128, |
| 12392 | .float_comptime_float, | 12413 | .float_comptime_float, |
| 12393 | .variable, | 12414 | .variable, |
| 12415 | .threadlocal_variable, | ||
| 12394 | .@"extern", | 12416 | .@"extern", |
| 12395 | .func_decl, | 12417 | .func_decl, |
| 12396 | .func_instance, | 12418 | .func_instance, |
src/Sema.zig+42-11| ... | @@ -26089,10 +26089,12 @@ fn resolveExternOptions( | ... | @@ -26089,10 +26089,12 @@ fn resolveExternOptions( |
| 26089 | zir_ref: Zir.Inst.Ref, | 26089 | zir_ref: Zir.Inst.Ref, |
| 26090 | ) CompileError!struct { | 26090 | ) CompileError!struct { |
| 26091 | name: InternPool.NullTerminatedString, | 26091 | name: InternPool.NullTerminatedString, |
| 26092 | library_name: InternPool.OptionalNullTerminatedString = .none, | 26092 | library_name: InternPool.OptionalNullTerminatedString, |
| 26093 | linkage: std.builtin.GlobalLinkage = .strong, | 26093 | linkage: std.builtin.GlobalLinkage, |
| 26094 | is_thread_local: bool = false, | 26094 | visibility: std.builtin.SymbolVisibility, |
| 26095 | is_dll_import: bool = false, | 26095 | is_thread_local: bool, |
| 26096 | is_dll_import: bool, | ||
| 26097 | relocation: std.builtin.ExternOptions.Relocation, | ||
| 26096 | } { | 26098 | } { |
| 26097 | const pt = sema.pt; | 26099 | const pt = sema.pt; |
| 26098 | const zcu = pt.zcu; | 26100 | const zcu = pt.zcu; |
| ... | @@ -26105,8 +26107,10 @@ fn resolveExternOptions( | ... | @@ -26105,8 +26107,10 @@ fn resolveExternOptions( |
| 26105 | const name_src = block.src(.{ .init_field_name = src.offset.node_offset_builtin_call_arg.builtin_call_node }); | 26107 | const name_src = block.src(.{ .init_field_name = src.offset.node_offset_builtin_call_arg.builtin_call_node }); |
| 26106 | const library_src = block.src(.{ .init_field_library = src.offset.node_offset_builtin_call_arg.builtin_call_node }); | 26108 | const library_src = block.src(.{ .init_field_library = src.offset.node_offset_builtin_call_arg.builtin_call_node }); |
| 26107 | const linkage_src = block.src(.{ .init_field_linkage = src.offset.node_offset_builtin_call_arg.builtin_call_node }); | 26109 | const linkage_src = block.src(.{ .init_field_linkage = src.offset.node_offset_builtin_call_arg.builtin_call_node }); |
| 26110 | const visibility_src = block.src(.{ .init_field_visibility = src.offset.node_offset_builtin_call_arg.builtin_call_node }); | ||
| 26108 | const thread_local_src = block.src(.{ .init_field_thread_local = src.offset.node_offset_builtin_call_arg.builtin_call_node }); | 26111 | const thread_local_src = block.src(.{ .init_field_thread_local = src.offset.node_offset_builtin_call_arg.builtin_call_node }); |
| 26109 | const dll_import_src = block.src(.{ .init_field_dll_import = src.offset.node_offset_builtin_call_arg.builtin_call_node }); | 26112 | const dll_import_src = block.src(.{ .init_field_dll_import = src.offset.node_offset_builtin_call_arg.builtin_call_node }); |
| 26113 | const relocation_src = block.src(.{ .init_field_relocation = src.offset.node_offset_builtin_call_arg.builtin_call_node }); | ||
| 26110 | 26114 | ||
| 26111 | const name_ref = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, pt.tid, "name", .no_embedded_nulls), name_src); | 26115 | const name_ref = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, pt.tid, "name", .no_embedded_nulls), name_src); |
| 26112 | const name = try sema.toConstString(block, name_src, name_ref, .{ .simple = .extern_options }); | 26116 | const name = try sema.toConstString(block, name_src, name_ref, .{ .simple = .extern_options }); |
| ... | @@ -26118,6 +26122,10 @@ fn resolveExternOptions( | ... | @@ -26118,6 +26122,10 @@ fn resolveExternOptions( |
| 26118 | const linkage_val = try sema.resolveConstDefinedValue(block, linkage_src, linkage_ref, .{ .simple = .extern_options }); | 26122 | const linkage_val = try sema.resolveConstDefinedValue(block, linkage_src, linkage_ref, .{ .simple = .extern_options }); |
| 26119 | const linkage = try sema.interpretBuiltinType(block, linkage_src, linkage_val, std.builtin.GlobalLinkage); | 26123 | const linkage = try sema.interpretBuiltinType(block, linkage_src, linkage_val, std.builtin.GlobalLinkage); |
| 26120 | 26124 | ||
| 26125 | const visibility_ref = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, pt.tid, "visibility", .no_embedded_nulls), visibility_src); | ||
| 26126 | const visibility_val = try sema.resolveConstDefinedValue(block, visibility_src, visibility_ref, .{ .simple = .extern_options }); | ||
| 26127 | const visibility = try sema.interpretBuiltinType(block, visibility_src, visibility_val, std.builtin.SymbolVisibility); | ||
| 26128 | |||
| 26121 | const is_thread_local = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, pt.tid, "is_thread_local", .no_embedded_nulls), thread_local_src); | 26129 | const is_thread_local = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, pt.tid, "is_thread_local", .no_embedded_nulls), thread_local_src); |
| 26122 | const is_thread_local_val = try sema.resolveConstDefinedValue(block, thread_local_src, is_thread_local, .{ .simple = .extern_options }); | 26130 | const is_thread_local_val = try sema.resolveConstDefinedValue(block, thread_local_src, is_thread_local, .{ .simple = .extern_options }); |
| 26123 | 26131 | ||
| ... | @@ -26133,6 +26141,10 @@ fn resolveExternOptions( | ... | @@ -26133,6 +26141,10 @@ fn resolveExternOptions( |
| 26133 | const is_dll_import_ref = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, pt.tid, "is_dll_import", .no_embedded_nulls), dll_import_src); | 26141 | const is_dll_import_ref = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, pt.tid, "is_dll_import", .no_embedded_nulls), dll_import_src); |
| 26134 | const is_dll_import_val = try sema.resolveConstDefinedValue(block, dll_import_src, is_dll_import_ref, .{ .simple = .extern_options }); | 26142 | const is_dll_import_val = try sema.resolveConstDefinedValue(block, dll_import_src, is_dll_import_ref, .{ .simple = .extern_options }); |
| 26135 | 26143 | ||
| 26144 | const relocation_ref = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, pt.tid, "relocation", .no_embedded_nulls), relocation_src); | ||
| 26145 | const relocation_val = try sema.resolveConstDefinedValue(block, relocation_src, relocation_ref, .{ .simple = .extern_options }); | ||
| 26146 | const relocation = try sema.interpretBuiltinType(block, relocation_src, relocation_val, std.builtin.ExternOptions.Relocation); | ||
| 26147 | |||
| 26136 | if (name.len == 0) { | 26148 | if (name.len == 0) { |
| 26137 | return sema.fail(block, name_src, "extern symbol name cannot be empty", .{}); | 26149 | return sema.fail(block, name_src, "extern symbol name cannot be empty", .{}); |
| 26138 | } | 26150 | } |
| ... | @@ -26145,8 +26157,10 @@ fn resolveExternOptions( | ... | @@ -26145,8 +26157,10 @@ fn resolveExternOptions( |
| 26145 | .name = try ip.getOrPutString(gpa, pt.tid, name, .no_embedded_nulls), | 26157 | .name = try ip.getOrPutString(gpa, pt.tid, name, .no_embedded_nulls), |
| 26146 | .library_name = try ip.getOrPutStringOpt(gpa, pt.tid, library_name, .no_embedded_nulls), | 26158 | .library_name = try ip.getOrPutStringOpt(gpa, pt.tid, library_name, .no_embedded_nulls), |
| 26147 | .linkage = linkage, | 26159 | .linkage = linkage, |
| 26160 | .visibility = visibility, | ||
| 26148 | .is_thread_local = is_thread_local_val.toBool(), | 26161 | .is_thread_local = is_thread_local_val.toBool(), |
| 26149 | .is_dll_import = is_dll_import_val.toBool(), | 26162 | .is_dll_import = is_dll_import_val.toBool(), |
| 26163 | .relocation = relocation, | ||
| 26150 | }; | 26164 | }; |
| 26151 | } | 26165 | } |
| 26152 | 26166 | ||
| ... | @@ -26178,6 +26192,17 @@ fn zirBuiltinExtern( | ... | @@ -26178,6 +26192,17 @@ fn zirBuiltinExtern( |
| 26178 | } | 26192 | } |
| 26179 | 26193 | ||
| 26180 | const options = try sema.resolveExternOptions(block, options_src, extra.rhs); | 26194 | const options = try sema.resolveExternOptions(block, options_src, extra.rhs); |
| 26195 | switch (options.linkage) { | ||
| 26196 | .internal => if (options.visibility != .default) { | ||
| 26197 | return sema.fail(block, options_src, "internal symbol cannot have non-default visibility", .{}); | ||
| 26198 | }, | ||
| 26199 | .strong, .weak => {}, | ||
| 26200 | .link_once => return sema.fail(block, options_src, "external symbol cannot have link once linkage", .{}), | ||
| 26201 | } | ||
| 26202 | switch (options.relocation) { | ||
| 26203 | .any => {}, | ||
| 26204 | .pcrel => if (options.visibility == .default) return sema.fail(block, options_src, "cannot require a pc-relative relocation to a symbol with default visibility", .{}), | ||
| 26205 | } | ||
| 26181 | 26206 | ||
| 26182 | // TODO: error for threadlocal functions, non-const functions, etc | 26207 | // TODO: error for threadlocal functions, non-const functions, etc |
| 26183 | 26208 | ||
| ... | @@ -26190,10 +26215,12 @@ fn zirBuiltinExtern( | ... | @@ -26190,10 +26215,12 @@ fn zirBuiltinExtern( |
| 26190 | .name = options.name, | 26215 | .name = options.name, |
| 26191 | .ty = ptr_info.child, | 26216 | .ty = ptr_info.child, |
| 26192 | .lib_name = options.library_name, | 26217 | .lib_name = options.library_name, |
| 26193 | .is_const = ptr_info.flags.is_const, | 26218 | .linkage = options.linkage, |
| 26219 | .visibility = options.visibility, | ||
| 26194 | .is_threadlocal = options.is_thread_local, | 26220 | .is_threadlocal = options.is_thread_local, |
| 26195 | .is_weak_linkage = options.linkage == .weak, | ||
| 26196 | .is_dll_import = options.is_dll_import, | 26221 | .is_dll_import = options.is_dll_import, |
| 26222 | .relocation = options.relocation, | ||
| 26223 | .is_const = ptr_info.flags.is_const, | ||
| 26197 | .alignment = ptr_info.flags.alignment, | 26224 | .alignment = ptr_info.flags.alignment, |
| 26198 | .@"addrspace" = ptr_info.flags.address_space, | 26225 | .@"addrspace" = ptr_info.flags.address_space, |
| 26199 | // This instruction is just for source locations. | 26226 | // This instruction is just for source locations. |
| ... | @@ -31685,12 +31712,15 @@ fn analyzeNavRefInner(sema: *Sema, block: *Block, src: LazySrcLoc, orig_nav_inde | ... | @@ -31685,12 +31712,15 @@ fn analyzeNavRefInner(sema: *Sema, block: *Block, src: LazySrcLoc, orig_nav_inde |
| 31685 | 31712 | ||
| 31686 | const nav_status = ip.getNav(nav_index).status; | 31713 | const nav_status = ip.getNav(nav_index).status; |
| 31687 | 31714 | ||
| 31688 | const is_tlv_or_dllimport = switch (nav_status) { | 31715 | const is_runtime = switch (nav_status) { |
| 31689 | .unresolved => unreachable, | 31716 | .unresolved => unreachable, |
| 31690 | // dllimports go straight to `fully_resolved`; the only option is threadlocal | 31717 | // dllimports go straight to `fully_resolved`; the only option is threadlocal |
| 31691 | .type_resolved => |r| r.is_threadlocal, | 31718 | .type_resolved => |r| r.is_threadlocal, |
| 31692 | .fully_resolved => |r| switch (ip.indexToKey(r.val)) { | 31719 | .fully_resolved => |r| switch (ip.indexToKey(r.val)) { |
| 31693 | .@"extern" => |e| e.is_threadlocal or e.is_dll_import, | 31720 | .@"extern" => |e| e.is_threadlocal or e.is_dll_import or switch (e.relocation) { |
| 31721 | .any => false, | ||
| 31722 | .pcrel => true, | ||
| 31723 | }, | ||
| 31694 | .variable => |v| v.is_threadlocal, | 31724 | .variable => |v| v.is_threadlocal, |
| 31695 | else => false, | 31725 | else => false, |
| 31696 | }, | 31726 | }, |
| ... | @@ -31699,7 +31729,7 @@ fn analyzeNavRefInner(sema: *Sema, block: *Block, src: LazySrcLoc, orig_nav_inde | ... | @@ -31699,7 +31729,7 @@ fn analyzeNavRefInner(sema: *Sema, block: *Block, src: LazySrcLoc, orig_nav_inde |
| 31699 | const ty, const alignment, const @"addrspace", const is_const = switch (nav_status) { | 31729 | const ty, const alignment, const @"addrspace", const is_const = switch (nav_status) { |
| 31700 | .unresolved => unreachable, | 31730 | .unresolved => unreachable, |
| 31701 | .type_resolved => |r| .{ r.type, r.alignment, r.@"addrspace", r.is_const }, | 31731 | .type_resolved => |r| .{ r.type, r.alignment, r.@"addrspace", r.is_const }, |
| 31702 | .fully_resolved => |r| .{ ip.typeOf(r.val), r.alignment, r.@"addrspace", zcu.navValIsConst(r.val) }, | 31732 | .fully_resolved => |r| .{ ip.typeOf(r.val), r.alignment, r.@"addrspace", r.is_const }, |
| 31703 | }; | 31733 | }; |
| 31704 | const ptr_ty = try pt.ptrTypeSema(.{ | 31734 | const ptr_ty = try pt.ptrTypeSema(.{ |
| 31705 | .child = ty, | 31735 | .child = ty, |
| ... | @@ -31710,10 +31740,10 @@ fn analyzeNavRefInner(sema: *Sema, block: *Block, src: LazySrcLoc, orig_nav_inde | ... | @@ -31710,10 +31740,10 @@ fn analyzeNavRefInner(sema: *Sema, block: *Block, src: LazySrcLoc, orig_nav_inde |
| 31710 | }, | 31740 | }, |
| 31711 | }); | 31741 | }); |
| 31712 | 31742 | ||
| 31713 | if (is_tlv_or_dllimport) { | 31743 | if (is_runtime) { |
| 31714 | // This pointer is runtime-known; we need to emit an AIR instruction to create it. | 31744 | // This pointer is runtime-known; we need to emit an AIR instruction to create it. |
| 31715 | return block.addInst(.{ | 31745 | return block.addInst(.{ |
| 31716 | .tag = .tlv_dllimport_ptr, | 31746 | .tag = .runtime_nav_ptr, |
| 31717 | .data = .{ .ty_nav = .{ | 31747 | .data = .{ .ty_nav = .{ |
| 31718 | .ty = ptr_ty.toIntern(), | 31748 | .ty = ptr_ty.toIntern(), |
| 31719 | .nav = nav_index, | 31749 | .nav = nav_index, |
| ... | @@ -36432,6 +36462,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { | ... | @@ -36432,6 +36462,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { |
| 36432 | .float_c_longdouble_f128, | 36462 | .float_c_longdouble_f128, |
| 36433 | .float_comptime_float, | 36463 | .float_comptime_float, |
| 36434 | .variable, | 36464 | .variable, |
| 36465 | .threadlocal_variable, | ||
| 36435 | .@"extern", | 36466 | .@"extern", |
| 36436 | .func_decl, | 36467 | .func_decl, |
| 36437 | .func_instance, | 36468 | .func_instance, |
src/Zcu.zig+3-9| ... | @@ -2047,6 +2047,7 @@ pub const SrcLoc = struct { | ... | @@ -2047,6 +2047,7 @@ pub const SrcLoc = struct { |
| 2047 | .init_field_library, | 2047 | .init_field_library, |
| 2048 | .init_field_thread_local, | 2048 | .init_field_thread_local, |
| 2049 | .init_field_dll_import, | 2049 | .init_field_dll_import, |
| 2050 | .init_field_relocation, | ||
| 2050 | => |builtin_call_node| { | 2051 | => |builtin_call_node| { |
| 2051 | const wanted = switch (src_loc.lazy) { | 2052 | const wanted = switch (src_loc.lazy) { |
| 2052 | .init_field_name => "name", | 2053 | .init_field_name => "name", |
| ... | @@ -2059,6 +2060,7 @@ pub const SrcLoc = struct { | ... | @@ -2059,6 +2060,7 @@ pub const SrcLoc = struct { |
| 2059 | .init_field_library => "library", | 2060 | .init_field_library => "library", |
| 2060 | .init_field_thread_local => "thread_local", | 2061 | .init_field_thread_local => "thread_local", |
| 2061 | .init_field_dll_import => "dll_import", | 2062 | .init_field_dll_import => "dll_import", |
| 2063 | .init_field_relocation => "relocation", | ||
| 2062 | else => unreachable, | 2064 | else => unreachable, |
| 2063 | }; | 2065 | }; |
| 2064 | const tree = try src_loc.file_scope.getTree(zcu); | 2066 | const tree = try src_loc.file_scope.getTree(zcu); |
| ... | @@ -2506,6 +2508,7 @@ pub const LazySrcLoc = struct { | ... | @@ -2506,6 +2508,7 @@ pub const LazySrcLoc = struct { |
| 2506 | init_field_library: Ast.Node.Offset, | 2508 | init_field_library: Ast.Node.Offset, |
| 2507 | init_field_thread_local: Ast.Node.Offset, | 2509 | init_field_thread_local: Ast.Node.Offset, |
| 2508 | init_field_dll_import: Ast.Node.Offset, | 2510 | init_field_dll_import: Ast.Node.Offset, |
| 2511 | init_field_relocation: Ast.Node.Offset, | ||
| 2509 | /// The source location points to the value of an item in a specific | 2512 | /// The source location points to the value of an item in a specific |
| 2510 | /// case of a `switch`. | 2513 | /// case of a `switch`. |
| 2511 | switch_case_item: SwitchItem, | 2514 | switch_case_item: SwitchItem, |
| ... | @@ -4562,15 +4565,6 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.builtin.CallingConvention) union(enu | ... | @@ -4562,15 +4565,6 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.builtin.CallingConvention) union(enu |
| 4562 | return .ok; | 4565 | return .ok; |
| 4563 | } | 4566 | } |
| 4564 | 4567 | ||
| 4565 | /// Given that a `Nav` has value `val`, determine if a ref of that `Nav` gives a `const` pointer. | ||
| 4566 | pub fn navValIsConst(zcu: *const Zcu, val: InternPool.Index) bool { | ||
| 4567 | return switch (zcu.intern_pool.indexToKey(val)) { | ||
| 4568 | .variable => false, | ||
| 4569 | .@"extern" => |e| e.is_const, | ||
| 4570 | else => true, | ||
| 4571 | }; | ||
| 4572 | } | ||
| 4573 | |||
| 4574 | pub const CodegenFailError = error{ | 4568 | pub const CodegenFailError = error{ |
| 4575 | /// Indicates the error message has been already stored at `Zcu.failed_codegen`. | 4569 | /// Indicates the error message has been already stored at `Zcu.failed_codegen`. |
| 4576 | CodegenFail, | 4570 | CodegenFail, |
src/Zcu/PerThread.zig+29-21| ... | @@ -1153,18 +1153,23 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr | ... | @@ -1153,18 +1153,23 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr |
| 1153 | // First, we must resolve the declaration's type. To do this, we analyze the type body if available, | 1153 | // First, we must resolve the declaration's type. To do this, we analyze the type body if available, |
| 1154 | // or otherwise, we analyze the value body, populating `early_val` in the process. | 1154 | // or otherwise, we analyze the value body, populating `early_val` in the process. |
| 1155 | 1155 | ||
| 1156 | switch (zir_decl.kind) { | 1156 | const is_const = is_const: switch (zir_decl.kind) { |
| 1157 | .@"comptime" => unreachable, // this is not a Nav | 1157 | .@"comptime" => unreachable, // this is not a Nav |
| 1158 | .unnamed_test, .@"test", .decltest => assert(nav_ty.zigTypeTag(zcu) == .@"fn"), | 1158 | .unnamed_test, .@"test", .decltest => { |
| 1159 | .@"usingnamespace" => {}, | 1159 | assert(nav_ty.zigTypeTag(zcu) == .@"fn"); |
| 1160 | .@"const" => {}, | 1160 | break :is_const true; |
| 1161 | .@"var" => try sema.validateVarType( | 1161 | }, |
| 1162 | &block, | 1162 | .@"usingnamespace", .@"const" => true, |
| 1163 | if (zir_decl.type_body != null) ty_src else init_src, | 1163 | .@"var" => { |
| 1164 | nav_ty, | 1164 | try sema.validateVarType( |
| 1165 | zir_decl.linkage == .@"extern", | 1165 | &block, |
| 1166 | ), | 1166 | if (zir_decl.type_body != null) ty_src else init_src, |
| 1167 | } | 1167 | nav_ty, |
| 1168 | zir_decl.linkage == .@"extern", | ||
| 1169 | ); | ||
| 1170 | break :is_const false; | ||
| 1171 | }, | ||
| 1172 | }; | ||
| 1168 | 1173 | ||
| 1169 | // Now that we know the type, we can evaluate the alignment, linksection, and addrspace, to determine | 1174 | // Now that we know the type, we can evaluate the alignment, linksection, and addrspace, to determine |
| 1170 | // the full pointer type of this declaration. | 1175 | // the full pointer type of this declaration. |
| ... | @@ -1195,7 +1200,6 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr | ... | @@ -1195,7 +1200,6 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr |
| 1195 | .init = final_val.?.toIntern(), | 1200 | .init = final_val.?.toIntern(), |
| 1196 | .owner_nav = nav_id, | 1201 | .owner_nav = nav_id, |
| 1197 | .is_threadlocal = zir_decl.is_threadlocal, | 1202 | .is_threadlocal = zir_decl.is_threadlocal, |
| 1198 | .is_weak_linkage = false, | ||
| 1199 | } })), | 1203 | } })), |
| 1200 | else => final_val.?, | 1204 | else => final_val.?, |
| 1201 | }, | 1205 | }, |
| ... | @@ -1212,10 +1216,12 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr | ... | @@ -1212,10 +1216,12 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr |
| 1212 | .name = old_nav.name, | 1216 | .name = old_nav.name, |
| 1213 | .ty = nav_ty.toIntern(), | 1217 | .ty = nav_ty.toIntern(), |
| 1214 | .lib_name = try ip.getOrPutStringOpt(gpa, pt.tid, lib_name, .no_embedded_nulls), | 1218 | .lib_name = try ip.getOrPutStringOpt(gpa, pt.tid, lib_name, .no_embedded_nulls), |
| 1215 | .is_const = zir_decl.kind == .@"const", | ||
| 1216 | .is_threadlocal = zir_decl.is_threadlocal, | 1219 | .is_threadlocal = zir_decl.is_threadlocal, |
| 1217 | .is_weak_linkage = false, | 1220 | .linkage = .strong, |
| 1221 | .visibility = .default, | ||
| 1218 | .is_dll_import = false, | 1222 | .is_dll_import = false, |
| 1223 | .relocation = .any, | ||
| 1224 | .is_const = is_const, | ||
| 1219 | .alignment = modifiers.alignment, | 1225 | .alignment = modifiers.alignment, |
| 1220 | .@"addrspace" = modifiers.@"addrspace", | 1226 | .@"addrspace" = modifiers.@"addrspace", |
| 1221 | .zir_index = old_nav.analysis.?.zir_index, // `declaration` instruction | 1227 | .zir_index = old_nav.analysis.?.zir_index, // `declaration` instruction |
| ... | @@ -1243,6 +1249,7 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr | ... | @@ -1243,6 +1249,7 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr |
| 1243 | } | 1249 | } |
| 1244 | ip.resolveNavValue(nav_id, .{ | 1250 | ip.resolveNavValue(nav_id, .{ |
| 1245 | .val = nav_val.toIntern(), | 1251 | .val = nav_val.toIntern(), |
| 1252 | .is_const = is_const, | ||
| 1246 | .alignment = .none, | 1253 | .alignment = .none, |
| 1247 | .@"linksection" = .none, | 1254 | .@"linksection" = .none, |
| 1248 | .@"addrspace" = .generic, | 1255 | .@"addrspace" = .generic, |
| ... | @@ -1286,6 +1293,7 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr | ... | @@ -1286,6 +1293,7 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr |
| 1286 | 1293 | ||
| 1287 | ip.resolveNavValue(nav_id, .{ | 1294 | ip.resolveNavValue(nav_id, .{ |
| 1288 | .val = nav_val.toIntern(), | 1295 | .val = nav_val.toIntern(), |
| 1296 | .is_const = is_const, | ||
| 1289 | .alignment = modifiers.alignment, | 1297 | .alignment = modifiers.alignment, |
| 1290 | .@"linksection" = modifiers.@"linksection", | 1298 | .@"linksection" = modifiers.@"linksection", |
| 1291 | .@"addrspace" = modifiers.@"addrspace", | 1299 | .@"addrspace" = modifiers.@"addrspace", |
| ... | @@ -1515,8 +1523,6 @@ fn analyzeNavType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileEr | ... | @@ -1515,8 +1523,6 @@ fn analyzeNavType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileEr |
| 1515 | // the pointer modifiers, i.e. alignment, linksection, addrspace. | 1523 | // the pointer modifiers, i.e. alignment, linksection, addrspace. |
| 1516 | const modifiers = try sema.resolveNavPtrModifiers(&block, zir_decl, inst_resolved.inst, resolved_ty); | 1524 | const modifiers = try sema.resolveNavPtrModifiers(&block, zir_decl, inst_resolved.inst, resolved_ty); |
| 1517 | 1525 | ||
| 1518 | // Usually, we can infer this information from the resolved `Nav` value; see `Zcu.navValIsConst`. | ||
| 1519 | // However, since we don't have one, we need to quickly check the ZIR to figure this out. | ||
| 1520 | const is_const = switch (zir_decl.kind) { | 1526 | const is_const = switch (zir_decl.kind) { |
| 1521 | .@"comptime" => unreachable, | 1527 | .@"comptime" => unreachable, |
| 1522 | .unnamed_test, .@"test", .decltest, .@"usingnamespace", .@"const" => true, | 1528 | .unnamed_test, .@"test", .decltest, .@"usingnamespace", .@"const" => true, |
| ... | @@ -1542,7 +1548,7 @@ fn analyzeNavType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileEr | ... | @@ -1542,7 +1548,7 @@ fn analyzeNavType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileEr |
| 1542 | r.alignment != modifiers.alignment or | 1548 | r.alignment != modifiers.alignment or |
| 1543 | r.@"linksection" != modifiers.@"linksection" or | 1549 | r.@"linksection" != modifiers.@"linksection" or |
| 1544 | r.@"addrspace" != modifiers.@"addrspace" or | 1550 | r.@"addrspace" != modifiers.@"addrspace" or |
| 1545 | zcu.navValIsConst(r.val) != is_const or | 1551 | r.is_const != is_const or |
| 1546 | (old_nav.getExtern(ip) != null) != is_extern_decl, | 1552 | (old_nav.getExtern(ip) != null) != is_extern_decl, |
| 1547 | }; | 1553 | }; |
| 1548 | 1554 | ||
| ... | @@ -1550,10 +1556,10 @@ fn analyzeNavType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileEr | ... | @@ -1550,10 +1556,10 @@ fn analyzeNavType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileEr |
| 1550 | 1556 | ||
| 1551 | ip.resolveNavType(nav_id, .{ | 1557 | ip.resolveNavType(nav_id, .{ |
| 1552 | .type = resolved_ty.toIntern(), | 1558 | .type = resolved_ty.toIntern(), |
| 1559 | .is_const = is_const, | ||
| 1553 | .alignment = modifiers.alignment, | 1560 | .alignment = modifiers.alignment, |
| 1554 | .@"linksection" = modifiers.@"linksection", | 1561 | .@"linksection" = modifiers.@"linksection", |
| 1555 | .@"addrspace" = modifiers.@"addrspace", | 1562 | .@"addrspace" = modifiers.@"addrspace", |
| 1556 | .is_const = is_const, | ||
| 1557 | .is_threadlocal = zir_decl.is_threadlocal, | 1563 | .is_threadlocal = zir_decl.is_threadlocal, |
| 1558 | .is_extern_decl = is_extern_decl, | 1564 | .is_extern_decl = is_extern_decl, |
| 1559 | }); | 1565 | }); |
| ... | @@ -1750,7 +1756,7 @@ pub fn linkerUpdateFunc(pt: Zcu.PerThread, func_index: InternPool.Index, air: *A | ... | @@ -1750,7 +1756,7 @@ pub fn linkerUpdateFunc(pt: Zcu.PerThread, func_index: InternPool.Index, air: *A |
| 1750 | 1756 | ||
| 1751 | if (build_options.enable_debug_extensions and comp.verbose_air) { | 1757 | if (build_options.enable_debug_extensions and comp.verbose_air) { |
| 1752 | std.debug.print("# Begin Function AIR: {}:\n", .{nav.fqn.fmt(ip)}); | 1758 | std.debug.print("# Begin Function AIR: {}:\n", .{nav.fqn.fmt(ip)}); |
| 1753 | @import("../print_air.zig").dump(pt, air.*, liveness); | 1759 | air.dump(pt, liveness); |
| 1754 | std.debug.print("# End Function AIR: {}\n\n", .{nav.fqn.fmt(ip)}); | 1760 | std.debug.print("# End Function AIR: {}\n\n", .{nav.fqn.fmt(ip)}); |
| 1755 | } | 1761 | } |
| 1756 | 1762 | ||
| ... | @@ -3577,8 +3583,10 @@ pub fn getCoerced(pt: Zcu.PerThread, val: Value, new_ty: Type) Allocator.Error!V | ... | @@ -3577,8 +3583,10 @@ pub fn getCoerced(pt: Zcu.PerThread, val: Value, new_ty: Type) Allocator.Error!V |
| 3577 | .lib_name = e.lib_name, | 3583 | .lib_name = e.lib_name, |
| 3578 | .is_const = e.is_const, | 3584 | .is_const = e.is_const, |
| 3579 | .is_threadlocal = e.is_threadlocal, | 3585 | .is_threadlocal = e.is_threadlocal, |
| 3580 | .is_weak_linkage = e.is_weak_linkage, | 3586 | .linkage = e.linkage, |
| 3587 | .visibility = e.visibility, | ||
| 3581 | .is_dll_import = e.is_dll_import, | 3588 | .is_dll_import = e.is_dll_import, |
| 3589 | .relocation = e.relocation, | ||
| 3582 | .alignment = e.alignment, | 3590 | .alignment = e.alignment, |
| 3583 | .@"addrspace" = e.@"addrspace", | 3591 | .@"addrspace" = e.@"addrspace", |
| 3584 | .zir_index = e.zir_index, | 3592 | .zir_index = e.zir_index, |
| ... | @@ -3954,7 +3962,7 @@ pub fn navPtrType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Allocator.Err | ... | @@ -3954,7 +3962,7 @@ pub fn navPtrType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Allocator.Err |
| 3954 | const ty, const alignment, const @"addrspace", const is_const = switch (ip.getNav(nav_id).status) { | 3962 | const ty, const alignment, const @"addrspace", const is_const = switch (ip.getNav(nav_id).status) { |
| 3955 | .unresolved => unreachable, | 3963 | .unresolved => unreachable, |
| 3956 | .type_resolved => |r| .{ r.type, r.alignment, r.@"addrspace", r.is_const }, | 3964 | .type_resolved => |r| .{ r.type, r.alignment, r.@"addrspace", r.is_const }, |
| 3957 | .fully_resolved => |r| .{ ip.typeOf(r.val), r.alignment, r.@"addrspace", zcu.navValIsConst(r.val) }, | 3965 | .fully_resolved => |r| .{ ip.typeOf(r.val), r.alignment, r.@"addrspace", r.is_const }, |
| 3958 | }; | 3966 | }; |
| 3959 | return pt.ptrType(.{ | 3967 | return pt.ptrType(.{ |
| 3960 | .child = ty, | 3968 | .child = ty, |
src/arch/aarch64/CodeGen.zig+1-1| ... | @@ -880,7 +880,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -880,7 +880,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 880 | .is_named_enum_value => return self.fail("TODO implement is_named_enum_value", .{}), | 880 | .is_named_enum_value => return self.fail("TODO implement is_named_enum_value", .{}), |
| 881 | .error_set_has_value => return self.fail("TODO implement error_set_has_value", .{}), | 881 | .error_set_has_value => return self.fail("TODO implement error_set_has_value", .{}), |
| 882 | .vector_store_elem => return self.fail("TODO implement vector_store_elem", .{}), | 882 | .vector_store_elem => return self.fail("TODO implement vector_store_elem", .{}), |
| 883 | .tlv_dllimport_ptr => return self.fail("TODO implement tlv_dllimport_ptr", .{}), | 883 | .runtime_nav_ptr => return self.fail("TODO implement runtime_nav_ptr", .{}), |
| 884 | 884 | ||
| 885 | .c_va_arg => return self.fail("TODO implement c_va_arg", .{}), | 885 | .c_va_arg => return self.fail("TODO implement c_va_arg", .{}), |
| 886 | .c_va_copy => return self.fail("TODO implement c_va_copy", .{}), | 886 | .c_va_copy => return self.fail("TODO implement c_va_copy", .{}), |
src/arch/arm/CodeGen.zig+1-1| ... | @@ -869,7 +869,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -869,7 +869,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 869 | .is_named_enum_value => return self.fail("TODO implement is_named_enum_value", .{}), | 869 | .is_named_enum_value => return self.fail("TODO implement is_named_enum_value", .{}), |
| 870 | .error_set_has_value => return self.fail("TODO implement error_set_has_value", .{}), | 870 | .error_set_has_value => return self.fail("TODO implement error_set_has_value", .{}), |
| 871 | .vector_store_elem => return self.fail("TODO implement vector_store_elem", .{}), | 871 | .vector_store_elem => return self.fail("TODO implement vector_store_elem", .{}), |
| 872 | .tlv_dllimport_ptr => return self.fail("TODO implement tlv_dllimport_ptr", .{}), | 872 | .runtime_nav_ptr => return self.fail("TODO implement runtime_nav_ptr", .{}), |
| 873 | 873 | ||
| 874 | .c_va_arg => return self.fail("TODO implement c_va_arg", .{}), | 874 | .c_va_arg => return self.fail("TODO implement c_va_arg", .{}), |
| 875 | .c_va_copy => return self.fail("TODO implement c_va_copy", .{}), | 875 | .c_va_copy => return self.fail("TODO implement c_va_copy", .{}), |
src/arch/riscv64/CodeGen.zig+4-9| ... | @@ -1041,12 +1041,7 @@ fn formatAir( | ... | @@ -1041,12 +1041,7 @@ fn formatAir( |
| 1041 | _: std.fmt.FormatOptions, | 1041 | _: std.fmt.FormatOptions, |
| 1042 | writer: anytype, | 1042 | writer: anytype, |
| 1043 | ) @TypeOf(writer).Error!void { | 1043 | ) @TypeOf(writer).Error!void { |
| 1044 | @import("../../print_air.zig").dumpInst( | 1044 | data.func.air.dumpInst(data.inst, data.func.pt, data.func.liveness); |
| 1045 | data.inst, | ||
| 1046 | data.func.pt, | ||
| 1047 | data.func.air, | ||
| 1048 | data.func.liveness, | ||
| 1049 | ); | ||
| 1050 | } | 1045 | } |
| 1051 | fn fmtAir(func: *Func, inst: Air.Inst.Index) std.fmt.Formatter(formatAir) { | 1046 | fn fmtAir(func: *Func, inst: Air.Inst.Index) std.fmt.Formatter(formatAir) { |
| 1052 | return .{ .data = .{ .func = func, .inst = inst } }; | 1047 | return .{ .data = .{ .func = func, .inst = inst } }; |
| ... | @@ -1656,7 +1651,7 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -1656,7 +1651,7 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void { |
| 1656 | .wrap_errunion_payload => try func.airWrapErrUnionPayload(inst), | 1651 | .wrap_errunion_payload => try func.airWrapErrUnionPayload(inst), |
| 1657 | .wrap_errunion_err => try func.airWrapErrUnionErr(inst), | 1652 | .wrap_errunion_err => try func.airWrapErrUnionErr(inst), |
| 1658 | 1653 | ||
| 1659 | .tlv_dllimport_ptr => try func.airTlvDllimportPtr(inst), | 1654 | .runtime_nav_ptr => try func.airRuntimeNavPtr(inst), |
| 1660 | 1655 | ||
| 1661 | .add_optimized, | 1656 | .add_optimized, |
| 1662 | .sub_optimized, | 1657 | .sub_optimized, |
| ... | @@ -3626,7 +3621,7 @@ fn airWrapErrUnionErr(func: *Func, inst: Air.Inst.Index) !void { | ... | @@ -3626,7 +3621,7 @@ fn airWrapErrUnionErr(func: *Func, inst: Air.Inst.Index) !void { |
| 3626 | return func.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | 3621 | return func.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 3627 | } | 3622 | } |
| 3628 | 3623 | ||
| 3629 | fn airTlvDllimportPtr(func: *Func, inst: Air.Inst.Index) !void { | 3624 | fn airRuntimeNavPtr(func: *Func, inst: Air.Inst.Index) !void { |
| 3630 | const zcu = func.pt.zcu; | 3625 | const zcu = func.pt.zcu; |
| 3631 | const ip = &zcu.intern_pool; | 3626 | const ip = &zcu.intern_pool; |
| 3632 | const ty_nav = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_nav; | 3627 | const ty_nav = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_nav; |
| ... | @@ -3641,7 +3636,7 @@ fn airTlvDllimportPtr(func: *Func, inst: Air.Inst.Index) !void { | ... | @@ -3641,7 +3636,7 @@ fn airTlvDllimportPtr(func: *Func, inst: Air.Inst.Index) !void { |
| 3641 | break :sym sym; | 3636 | break :sym sym; |
| 3642 | } | 3637 | } |
| 3643 | break :sym try zo.getOrCreateMetadataForNav(zcu, ty_nav.nav); | 3638 | break :sym try zo.getOrCreateMetadataForNav(zcu, ty_nav.nav); |
| 3644 | } else return func.fail("TODO tlv_dllimport_ptr on {}", .{func.bin_file.tag}); | 3639 | } else return func.fail("TODO runtime_nav_ptr on {}", .{func.bin_file.tag}); |
| 3645 | 3640 | ||
| 3646 | const dest_mcv = try func.allocRegOrMem(ptr_ty, inst, true); | 3641 | const dest_mcv = try func.allocRegOrMem(ptr_ty, inst, true); |
| 3647 | if (dest_mcv.isRegister()) { | 3642 | if (dest_mcv.isRegister()) { |
src/arch/sparc64/CodeGen.zig+1-1| ... | @@ -723,7 +723,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -723,7 +723,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 723 | .is_named_enum_value => @panic("TODO implement is_named_enum_value"), | 723 | .is_named_enum_value => @panic("TODO implement is_named_enum_value"), |
| 724 | .error_set_has_value => @panic("TODO implement error_set_has_value"), | 724 | .error_set_has_value => @panic("TODO implement error_set_has_value"), |
| 725 | .vector_store_elem => @panic("TODO implement vector_store_elem"), | 725 | .vector_store_elem => @panic("TODO implement vector_store_elem"), |
| 726 | .tlv_dllimport_ptr => @panic("TODO implement tlv_dllimport_ptr"), | 726 | .runtime_nav_ptr => @panic("TODO implement runtime_nav_ptr"), |
| 727 | 727 | ||
| 728 | .c_va_arg => return self.fail("TODO implement c_va_arg", .{}), | 728 | .c_va_arg => return self.fail("TODO implement c_va_arg", .{}), |
| 729 | .c_va_copy => return self.fail("TODO implement c_va_copy", .{}), | 729 | .c_va_copy => return self.fail("TODO implement c_va_copy", .{}), |
src/arch/wasm/CodeGen.zig+2-2| ... | @@ -2057,7 +2057,7 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -2057,7 +2057,7 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 2057 | .error_set_has_value => cg.airErrorSetHasValue(inst), | 2057 | .error_set_has_value => cg.airErrorSetHasValue(inst), |
| 2058 | .frame_addr => cg.airFrameAddress(inst), | 2058 | .frame_addr => cg.airFrameAddress(inst), |
| 2059 | 2059 | ||
| 2060 | .tlv_dllimport_ptr => cg.airTlvDllimportPtr(inst), | 2060 | .runtime_nav_ptr => cg.airRuntimeNavPtr(inst), |
| 2061 | 2061 | ||
| 2062 | .assembly, | 2062 | .assembly, |
| 2063 | .is_err_ptr, | 2063 | .is_err_ptr, |
| ... | @@ -7616,7 +7616,7 @@ fn airFrameAddress(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -7616,7 +7616,7 @@ fn airFrameAddress(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 7616 | return cg.finishAir(inst, .stack, &.{}); | 7616 | return cg.finishAir(inst, .stack, &.{}); |
| 7617 | } | 7617 | } |
| 7618 | 7618 | ||
| 7619 | fn airTlvDllimportPtr(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { | 7619 | fn airRuntimeNavPtr(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 7620 | const ty_nav = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_nav; | 7620 | const ty_nav = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_nav; |
| 7621 | const mod = cg.pt.zcu.navFileScope(cg.owner_nav).mod.?; | 7621 | const mod = cg.pt.zcu.navFileScope(cg.owner_nav).mod.?; |
| 7622 | if (mod.single_threaded) { | 7622 | if (mod.single_threaded) { |
src/arch/x86_64/CodeGen.zig+173-42| ... | @@ -274,6 +274,12 @@ pub const MCValue = union(enum) { | ... | @@ -274,6 +274,12 @@ pub const MCValue = union(enum) { |
| 274 | load_symbol: bits.SymbolOffset, | 274 | load_symbol: bits.SymbolOffset, |
| 275 | /// The address of the memory location not-yet-allocated by the linker. | 275 | /// The address of the memory location not-yet-allocated by the linker. |
| 276 | lea_symbol: bits.SymbolOffset, | 276 | lea_symbol: bits.SymbolOffset, |
| 277 | /// The value is in memory at an address not-yet-allocated by the linker. | ||
| 278 | /// This must use a non-got pc-relative relocation. | ||
| 279 | load_pcrel: bits.SymbolOffset, | ||
| 280 | /// The address of the memory location not-yet-allocated by the linker. | ||
| 281 | /// This must use a non-got pc-relative relocation. | ||
| 282 | lea_pcrel: bits.SymbolOffset, | ||
| 277 | /// The value is in memory at a constant offset from the address in a register. | 283 | /// The value is in memory at a constant offset from the address in a register. |
| 278 | indirect: bits.RegisterOffset, | 284 | indirect: bits.RegisterOffset, |
| 279 | /// The value is in memory. | 285 | /// The value is in memory. |
| ... | @@ -314,6 +320,7 @@ pub const MCValue = union(enum) { | ... | @@ -314,6 +320,7 @@ pub const MCValue = union(enum) { |
| 314 | .eflags, | 320 | .eflags, |
| 315 | .register_overflow, | 321 | .register_overflow, |
| 316 | .lea_symbol, | 322 | .lea_symbol, |
| 323 | .lea_pcrel, | ||
| 317 | .lea_direct, | 324 | .lea_direct, |
| 318 | .lea_got, | 325 | .lea_got, |
| 319 | .lea_frame, | 326 | .lea_frame, |
| ... | @@ -327,6 +334,7 @@ pub const MCValue = union(enum) { | ... | @@ -327,6 +334,7 @@ pub const MCValue = union(enum) { |
| 327 | .register_quadruple, | 334 | .register_quadruple, |
| 328 | .memory, | 335 | .memory, |
| 329 | .load_symbol, | 336 | .load_symbol, |
| 337 | .load_pcrel, | ||
| 330 | .load_got, | 338 | .load_got, |
| 331 | .load_direct, | 339 | .load_direct, |
| 332 | .indirect, | 340 | .indirect, |
| ... | @@ -429,6 +437,7 @@ pub const MCValue = union(enum) { | ... | @@ -429,6 +437,7 @@ pub const MCValue = union(enum) { |
| 429 | .register_overflow, | 437 | .register_overflow, |
| 430 | .register_mask, | 438 | .register_mask, |
| 431 | .lea_symbol, | 439 | .lea_symbol, |
| 440 | .lea_pcrel, | ||
| 432 | .lea_direct, | 441 | .lea_direct, |
| 433 | .lea_got, | 442 | .lea_got, |
| 434 | .lea_frame, | 443 | .lea_frame, |
| ... | @@ -445,6 +454,7 @@ pub const MCValue = union(enum) { | ... | @@ -445,6 +454,7 @@ pub const MCValue = union(enum) { |
| 445 | .load_got => |sym_index| .{ .lea_got = sym_index }, | 454 | .load_got => |sym_index| .{ .lea_got = sym_index }, |
| 446 | .load_frame => |frame_addr| .{ .lea_frame = frame_addr }, | 455 | .load_frame => |frame_addr| .{ .lea_frame = frame_addr }, |
| 447 | .load_symbol => |sym_off| .{ .lea_symbol = sym_off }, | 456 | .load_symbol => |sym_off| .{ .lea_symbol = sym_off }, |
| 457 | .load_pcrel => |sym_off| .{ .lea_pcrel = sym_off }, | ||
| 448 | }; | 458 | }; |
| 449 | } | 459 | } |
| 450 | 460 | ||
| ... | @@ -466,6 +476,7 @@ pub const MCValue = union(enum) { | ... | @@ -466,6 +476,7 @@ pub const MCValue = union(enum) { |
| 466 | .load_got, | 476 | .load_got, |
| 467 | .load_frame, | 477 | .load_frame, |
| 468 | .load_symbol, | 478 | .load_symbol, |
| 479 | .load_pcrel, | ||
| 469 | .elementwise_args, | 480 | .elementwise_args, |
| 470 | .reserved_frame, | 481 | .reserved_frame, |
| 471 | .air_ref, | 482 | .air_ref, |
| ... | @@ -477,6 +488,7 @@ pub const MCValue = union(enum) { | ... | @@ -477,6 +488,7 @@ pub const MCValue = union(enum) { |
| 477 | .lea_got => |sym_index| .{ .load_got = sym_index }, | 488 | .lea_got => |sym_index| .{ .load_got = sym_index }, |
| 478 | .lea_frame => |frame_addr| .{ .load_frame = frame_addr }, | 489 | .lea_frame => |frame_addr| .{ .load_frame = frame_addr }, |
| 479 | .lea_symbol => |sym_index| .{ .load_symbol = sym_index }, | 490 | .lea_symbol => |sym_index| .{ .load_symbol = sym_index }, |
| 491 | .lea_pcrel => |sym_index| .{ .load_pcrel = sym_index }, | ||
| 480 | }; | 492 | }; |
| 481 | } | 493 | } |
| 482 | 494 | ||
| ... | @@ -505,6 +517,8 @@ pub const MCValue = union(enum) { | ... | @@ -505,6 +517,8 @@ pub const MCValue = union(enum) { |
| 505 | .load_frame, | 517 | .load_frame, |
| 506 | .load_symbol, | 518 | .load_symbol, |
| 507 | .lea_symbol, | 519 | .lea_symbol, |
| 520 | .load_pcrel, | ||
| 521 | .lea_pcrel, | ||
| 508 | => switch (off) { | 522 | => switch (off) { |
| 509 | 0 => mcv, | 523 | 0 => mcv, |
| 510 | else => unreachable, // not offsettable | 524 | else => unreachable, // not offsettable |
| ... | @@ -543,6 +557,7 @@ pub const MCValue = union(enum) { | ... | @@ -543,6 +557,7 @@ pub const MCValue = union(enum) { |
| 543 | .elementwise_args, | 557 | .elementwise_args, |
| 544 | .reserved_frame, | 558 | .reserved_frame, |
| 545 | .lea_symbol, | 559 | .lea_symbol, |
| 560 | .lea_pcrel, | ||
| 546 | => unreachable, | 561 | => unreachable, |
| 547 | .memory => |addr| if (std.math.cast(i32, @as(i64, @bitCast(addr)))) |small_addr| .{ | 562 | .memory => |addr| if (std.math.cast(i32, @as(i64, @bitCast(addr)))) |small_addr| .{ |
| 548 | .base = .{ .reg = .ds }, | 563 | .base = .{ .reg = .ds }, |
| ... | @@ -583,6 +598,18 @@ pub const MCValue = union(enum) { | ... | @@ -583,6 +598,18 @@ pub const MCValue = union(enum) { |
| 583 | } }, | 598 | } }, |
| 584 | }; | 599 | }; |
| 585 | }, | 600 | }, |
| 601 | .load_pcrel => |sym_off| { | ||
| 602 | assert(sym_off.off == 0); | ||
| 603 | return .{ | ||
| 604 | .base = .{ .pcrel = sym_off.sym_index }, | ||
| 605 | .mod = .{ .rm = .{ | ||
| 606 | .size = mod_rm.size, | ||
| 607 | .index = mod_rm.index, | ||
| 608 | .scale = mod_rm.scale, | ||
| 609 | .disp = sym_off.off + mod_rm.disp, | ||
| 610 | } }, | ||
| 611 | }; | ||
| 612 | }, | ||
| 586 | .air_ref => |ref| (try function.resolveInst(ref)).mem(function, mod_rm), | 613 | .air_ref => |ref| (try function.resolveInst(ref)).mem(function, mod_rm), |
| 587 | }; | 614 | }; |
| 588 | } | 615 | } |
| ... | @@ -618,6 +645,8 @@ pub const MCValue = union(enum) { | ... | @@ -618,6 +645,8 @@ pub const MCValue = union(enum) { |
| 618 | }), | 645 | }), |
| 619 | .load_symbol => |pl| try writer.print("[sym:{} + 0x{x}]", .{ pl.sym_index, pl.off }), | 646 | .load_symbol => |pl| try writer.print("[sym:{} + 0x{x}]", .{ pl.sym_index, pl.off }), |
| 620 | .lea_symbol => |pl| try writer.print("sym:{} + 0x{x}", .{ pl.sym_index, pl.off }), | 647 | .lea_symbol => |pl| try writer.print("sym:{} + 0x{x}", .{ pl.sym_index, pl.off }), |
| 648 | .load_pcrel => |pl| try writer.print("[sym@pcrel:{} + 0x{x}]", .{ pl.sym_index, pl.off }), | ||
| 649 | .lea_pcrel => |pl| try writer.print("sym@pcrel:{} + 0x{x}", .{ pl.sym_index, pl.off }), | ||
| 621 | .indirect => |pl| try writer.print("[{s} + 0x{x}]", .{ @tagName(pl.reg), pl.off }), | 650 | .indirect => |pl| try writer.print("[{s} + 0x{x}]", .{ @tagName(pl.reg), pl.off }), |
| 622 | .load_direct => |pl| try writer.print("[direct:{d}]", .{pl}), | 651 | .load_direct => |pl| try writer.print("[direct:{d}]", .{pl}), |
| 623 | .lea_direct => |pl| try writer.print("direct:{d}", .{pl}), | 652 | .lea_direct => |pl| try writer.print("direct:{d}", .{pl}), |
| ... | @@ -655,6 +684,8 @@ const InstTracking = struct { | ... | @@ -655,6 +684,8 @@ const InstTracking = struct { |
| 655 | .lea_frame, | 684 | .lea_frame, |
| 656 | .load_symbol, | 685 | .load_symbol, |
| 657 | .lea_symbol, | 686 | .lea_symbol, |
| 687 | .load_pcrel, | ||
| 688 | .lea_pcrel, | ||
| 658 | => result, | 689 | => result, |
| 659 | .dead, | 690 | .dead, |
| 660 | .elementwise_args, | 691 | .elementwise_args, |
| ... | @@ -755,6 +786,8 @@ const InstTracking = struct { | ... | @@ -755,6 +786,8 @@ const InstTracking = struct { |
| 755 | .lea_frame, | 786 | .lea_frame, |
| 756 | .load_symbol, | 787 | .load_symbol, |
| 757 | .lea_symbol, | 788 | .lea_symbol, |
| 789 | .load_pcrel, | ||
| 790 | .lea_pcrel, | ||
| 758 | => assert(std.meta.eql(self.long, target.long)), | 791 | => assert(std.meta.eql(self.long, target.long)), |
| 759 | .dead, | 792 | .dead, |
| 760 | .eflags, | 793 | .eflags, |
| ... | @@ -1228,12 +1261,7 @@ fn formatAir( | ... | @@ -1228,12 +1261,7 @@ fn formatAir( |
| 1228 | _: std.fmt.FormatOptions, | 1261 | _: std.fmt.FormatOptions, |
| 1229 | writer: anytype, | 1262 | writer: anytype, |
| 1230 | ) @TypeOf(writer).Error!void { | 1263 | ) @TypeOf(writer).Error!void { |
| 1231 | @import("../../print_air.zig").dumpInst( | 1264 | data.self.air.dumpInst(data.inst, data.self.pt, data.self.liveness); |
| 1232 | data.inst, | ||
| 1233 | data.self.pt, | ||
| 1234 | data.self.air, | ||
| 1235 | data.self.liveness, | ||
| 1236 | ); | ||
| 1237 | } | 1265 | } |
| 1238 | fn fmtAir(self: *CodeGen, inst: Air.Inst.Index) std.fmt.Formatter(formatAir) { | 1266 | fn fmtAir(self: *CodeGen, inst: Air.Inst.Index) std.fmt.Formatter(formatAir) { |
| 1239 | return .{ .data = .{ .self = self, .inst = inst } }; | 1267 | return .{ .data = .{ .self = self, .inst = inst } }; |
| ... | @@ -163487,31 +163515,49 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -163487,31 +163515,49 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 163487 | }; | 163515 | }; |
| 163488 | for (ops) |op| try op.die(cg); | 163516 | for (ops) |op| try op.die(cg); |
| 163489 | }, | 163517 | }, |
| 163490 | .tlv_dllimport_ptr => switch (cg.bin_file.tag) { | 163518 | .runtime_nav_ptr => switch (cg.bin_file.tag) { |
| 163491 | .elf, .macho => { | 163519 | .elf, .macho => { |
| 163492 | const ty_nav = air_datas[@intFromEnum(inst)].ty_nav; | 163520 | const ty_nav = air_datas[@intFromEnum(inst)].ty_nav; |
| 163493 | 163521 | ||
| 163494 | const nav = ip.getNav(ty_nav.nav); | 163522 | const nav = ip.getNav(ty_nav.nav); |
| 163495 | const tlv_sym_index = sym: { | 163523 | const sym_index, const relocation = sym: { |
| 163496 | if (cg.bin_file.cast(.elf)) |elf_file| { | 163524 | if (cg.bin_file.cast(.elf)) |elf_file| { |
| 163497 | const zo = elf_file.zigObjectPtr().?; | 163525 | const zo = elf_file.zigObjectPtr().?; |
| 163498 | if (nav.getExtern(ip)) |e| { | 163526 | if (nav.getExtern(ip)) |e| { |
| 163499 | const sym = try elf_file.getGlobalSymbol(nav.name.toSlice(ip), e.lib_name.toSlice(ip)); | 163527 | const sym = try elf_file.getGlobalSymbol(nav.name.toSlice(ip), e.lib_name.toSlice(ip)); |
| 163500 | zo.symbol(sym).flags.is_extern_ptr = true; | 163528 | linkage: switch (e.linkage) { |
| 163501 | break :sym sym; | 163529 | .internal => {}, |
| 163502 | } | 163530 | .strong => switch (e.visibility) { |
| 163503 | break :sym try zo.getOrCreateMetadataForNav(zcu, ty_nav.nav); | 163531 | .default => zo.symbol(sym).flags.is_extern_ptr = true, |
| 163504 | } | 163532 | .hidden, .protected => {}, |
| 163505 | if (cg.bin_file.cast(.macho)) |macho_file| { | 163533 | }, |
| 163534 | .weak => { | ||
| 163535 | zo.symbol(sym).flags.weak = true; | ||
| 163536 | continue :linkage .strong; | ||
| 163537 | }, | ||
| 163538 | .link_once => unreachable, | ||
| 163539 | } | ||
| 163540 | break :sym .{ sym, e.relocation }; | ||
| 163541 | } else break :sym .{ try zo.getOrCreateMetadataForNav(zcu, ty_nav.nav), .any }; | ||
| 163542 | } else if (cg.bin_file.cast(.macho)) |macho_file| { | ||
| 163506 | const zo = macho_file.getZigObject().?; | 163543 | const zo = macho_file.getZigObject().?; |
| 163507 | if (nav.getExtern(ip)) |e| { | 163544 | if (nav.getExtern(ip)) |e| { |
| 163508 | const sym = try macho_file.getGlobalSymbol(nav.name.toSlice(ip), e.lib_name.toSlice(ip)); | 163545 | const sym = try macho_file.getGlobalSymbol(nav.name.toSlice(ip), e.lib_name.toSlice(ip)); |
| 163509 | zo.symbols.items[sym].flags.is_extern_ptr = true; | 163546 | linkage: switch (e.linkage) { |
| 163510 | break :sym sym; | 163547 | .internal => {}, |
| 163511 | } | 163548 | .strong => switch (e.visibility) { |
| 163512 | break :sym try zo.getOrCreateMetadataForNav(macho_file, ty_nav.nav); | 163549 | .default => zo.symbols.items[sym].flags.is_extern_ptr = true, |
| 163513 | } | 163550 | .hidden, .protected => {}, |
| 163514 | unreachable; | 163551 | }, |
| 163552 | .weak => { | ||
| 163553 | zo.symbols.items[sym].flags.weak = true; | ||
| 163554 | continue :linkage .strong; | ||
| 163555 | }, | ||
| 163556 | .link_once => unreachable, | ||
| 163557 | } | ||
| 163558 | break :sym .{ sym, e.relocation }; | ||
| 163559 | } else break :sym .{ try zo.getOrCreateMetadataForNav(macho_file, ty_nav.nav), .any }; | ||
| 163560 | } else unreachable; | ||
| 163515 | }; | 163561 | }; |
| 163516 | 163562 | ||
| 163517 | if (cg.mod.pic) { | 163563 | if (cg.mod.pic) { |
| ... | @@ -163520,13 +163566,14 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -163520,13 +163566,14 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 163520 | try cg.spillRegisters(&.{.rax}); | 163566 | try cg.spillRegisters(&.{.rax}); |
| 163521 | } | 163567 | } |
| 163522 | 163568 | ||
| 163523 | var slot = try cg.tempInit(.usize, .{ .lea_symbol = .{ | 163569 | var slot = try cg.tempInit(.usize, switch (relocation) { |
| 163524 | .sym_index = tlv_sym_index, | 163570 | .any => .{ .lea_symbol = .{ .sym_index = sym_index } }, |
| 163525 | } }); | 163571 | .pcrel => .{ .lea_pcrel = .{ .sym_index = sym_index } }, |
| 163572 | }); | ||
| 163526 | while (try slot.toRegClass(true, .general_purpose, cg)) {} | 163573 | while (try slot.toRegClass(true, .general_purpose, cg)) {} |
| 163527 | try slot.finish(inst, &.{}, &.{}, cg); | 163574 | try slot.finish(inst, &.{}, &.{}, cg); |
| 163528 | }, | 163575 | }, |
| 163529 | else => return cg.fail("TODO implement tlv/dllimport on {}", .{cg.bin_file.tag}), | 163576 | else => return cg.fail("TODO implement runtime_nav_ptr on {}", .{cg.bin_file.tag}), |
| 163530 | }, | 163577 | }, |
| 163531 | .c_va_arg => try cg.airVaArg(inst), | 163578 | .c_va_arg => try cg.airVaArg(inst), |
| 163532 | .c_va_copy => try cg.airVaCopy(inst), | 163579 | .c_va_copy => try cg.airVaCopy(inst), |
| ... | @@ -169189,6 +169236,7 @@ fn load(self: *CodeGen, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) InnerE | ... | @@ -169189,6 +169236,7 @@ fn load(self: *CodeGen, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) InnerE |
| 169189 | .register, | 169236 | .register, |
| 169190 | .register_offset, | 169237 | .register_offset, |
| 169191 | .lea_symbol, | 169238 | .lea_symbol, |
| 169239 | .lea_pcrel, | ||
| 169192 | .lea_direct, | 169240 | .lea_direct, |
| 169193 | .lea_got, | 169241 | .lea_got, |
| 169194 | .lea_frame, | 169242 | .lea_frame, |
| ... | @@ -169196,6 +169244,7 @@ fn load(self: *CodeGen, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) InnerE | ... | @@ -169196,6 +169244,7 @@ fn load(self: *CodeGen, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) InnerE |
| 169196 | .memory, | 169244 | .memory, |
| 169197 | .indirect, | 169245 | .indirect, |
| 169198 | .load_symbol, | 169246 | .load_symbol, |
| 169247 | .load_pcrel, | ||
| 169199 | .load_direct, | 169248 | .load_direct, |
| 169200 | .load_got, | 169249 | .load_got, |
| 169201 | .load_frame, | 169250 | .load_frame, |
| ... | @@ -169407,6 +169456,7 @@ fn store( | ... | @@ -169407,6 +169456,7 @@ fn store( |
| 169407 | .register, | 169456 | .register, |
| 169408 | .register_offset, | 169457 | .register_offset, |
| 169409 | .lea_symbol, | 169458 | .lea_symbol, |
| 169459 | .lea_pcrel, | ||
| 169410 | .lea_direct, | 169460 | .lea_direct, |
| 169411 | .lea_got, | 169461 | .lea_got, |
| 169412 | .lea_frame, | 169462 | .lea_frame, |
| ... | @@ -169414,6 +169464,7 @@ fn store( | ... | @@ -169414,6 +169464,7 @@ fn store( |
| 169414 | .memory, | 169464 | .memory, |
| 169415 | .indirect, | 169465 | .indirect, |
| 169416 | .load_symbol, | 169466 | .load_symbol, |
| 169467 | .load_pcrel, | ||
| 169417 | .load_direct, | 169468 | .load_direct, |
| 169418 | .load_got, | 169469 | .load_got, |
| 169419 | .load_frame, | 169470 | .load_frame, |
| ... | @@ -169883,6 +169934,7 @@ fn genUnOpMir(self: *CodeGen, mir_tag: Mir.Inst.FixedTag, dst_ty: Type, dst_mcv: | ... | @@ -169883,6 +169934,7 @@ fn genUnOpMir(self: *CodeGen, mir_tag: Mir.Inst.FixedTag, dst_ty: Type, dst_mcv: |
| 169883 | .register_overflow, | 169934 | .register_overflow, |
| 169884 | .register_mask, | 169935 | .register_mask, |
| 169885 | .lea_symbol, | 169936 | .lea_symbol, |
| 169937 | .lea_pcrel, | ||
| 169886 | .lea_direct, | 169938 | .lea_direct, |
| 169887 | .lea_got, | 169939 | .lea_got, |
| 169888 | .lea_frame, | 169940 | .lea_frame, |
| ... | @@ -169892,7 +169944,7 @@ fn genUnOpMir(self: *CodeGen, mir_tag: Mir.Inst.FixedTag, dst_ty: Type, dst_mcv: | ... | @@ -169892,7 +169944,7 @@ fn genUnOpMir(self: *CodeGen, mir_tag: Mir.Inst.FixedTag, dst_ty: Type, dst_mcv: |
| 169892 | => unreachable, // unmodifiable destination | 169944 | => unreachable, // unmodifiable destination |
| 169893 | .register => |dst_reg| try self.asmRegister(mir_tag, registerAlias(dst_reg, abi_size)), | 169945 | .register => |dst_reg| try self.asmRegister(mir_tag, registerAlias(dst_reg, abi_size)), |
| 169894 | .register_pair, .register_triple, .register_quadruple => unreachable, // unimplemented | 169946 | .register_pair, .register_triple, .register_quadruple => unreachable, // unimplemented |
| 169895 | .memory, .load_symbol, .load_got, .load_direct => { | 169947 | .memory, .load_symbol, .load_pcrel, .load_got, .load_direct => { |
| 169896 | const addr_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp); | 169948 | const addr_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp); |
| 169897 | const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg); | 169949 | const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg); |
| 169898 | defer self.register_manager.unlockReg(addr_reg_lock); | 169950 | defer self.register_manager.unlockReg(addr_reg_lock); |
| ... | @@ -171552,6 +171604,8 @@ fn genBinOp( | ... | @@ -171552,6 +171604,8 @@ fn genBinOp( |
| 171552 | .register_mask, | 171604 | .register_mask, |
| 171553 | .load_symbol, | 171605 | .load_symbol, |
| 171554 | .lea_symbol, | 171606 | .lea_symbol, |
| 171607 | .load_pcrel, | ||
| 171608 | .lea_pcrel, | ||
| 171555 | .load_direct, | 171609 | .load_direct, |
| 171556 | .lea_direct, | 171610 | .lea_direct, |
| 171557 | .load_got, | 171611 | .load_got, |
| ... | @@ -172740,6 +172794,7 @@ fn genBinOpMir( | ... | @@ -172740,6 +172794,7 @@ fn genBinOpMir( |
| 172740 | .lea_got, | 172794 | .lea_got, |
| 172741 | .lea_frame, | 172795 | .lea_frame, |
| 172742 | .lea_symbol, | 172796 | .lea_symbol, |
| 172797 | .lea_pcrel, | ||
| 172743 | .elementwise_args, | 172798 | .elementwise_args, |
| 172744 | .reserved_frame, | 172799 | .reserved_frame, |
| 172745 | .air_ref, | 172800 | .air_ref, |
| ... | @@ -172831,6 +172886,8 @@ fn genBinOpMir( | ... | @@ -172831,6 +172886,8 @@ fn genBinOpMir( |
| 172831 | .indirect, | 172886 | .indirect, |
| 172832 | .load_symbol, | 172887 | .load_symbol, |
| 172833 | .lea_symbol, | 172888 | .lea_symbol, |
| 172889 | .load_pcrel, | ||
| 172890 | .lea_pcrel, | ||
| 172834 | .load_direct, | 172891 | .load_direct, |
| 172835 | .lea_direct, | 172892 | .lea_direct, |
| 172836 | .load_got, | 172893 | .load_got, |
| ... | @@ -172906,7 +172963,7 @@ fn genBinOpMir( | ... | @@ -172906,7 +172963,7 @@ fn genBinOpMir( |
| 172906 | } | 172963 | } |
| 172907 | } | 172964 | } |
| 172908 | }, | 172965 | }, |
| 172909 | .memory, .indirect, .load_symbol, .load_got, .load_direct, .load_frame => { | 172966 | .memory, .indirect, .load_symbol, .load_pcrel, .load_got, .load_direct, .load_frame => { |
| 172910 | const OpInfo = ?struct { addr_reg: Register, addr_lock: RegisterLock }; | 172967 | const OpInfo = ?struct { addr_reg: Register, addr_lock: RegisterLock }; |
| 172911 | const limb_abi_size: u32 = @min(abi_size, 8); | 172968 | const limb_abi_size: u32 = @min(abi_size, 8); |
| 172912 | 172969 | ||
| ... | @@ -172953,8 +173010,9 @@ fn genBinOpMir( | ... | @@ -172953,8 +173010,9 @@ fn genBinOpMir( |
| 172953 | .load_frame, | 173010 | .load_frame, |
| 172954 | .lea_frame, | 173011 | .lea_frame, |
| 172955 | .lea_symbol, | 173012 | .lea_symbol, |
| 173013 | .lea_pcrel, | ||
| 172956 | => null, | 173014 | => null, |
| 172957 | .memory, .load_symbol, .load_got, .load_direct => src: { | 173015 | .memory, .load_symbol, .load_pcrel, .load_got, .load_direct => src: { |
| 172958 | switch (resolved_src_mcv) { | 173016 | switch (resolved_src_mcv) { |
| 172959 | .memory => |addr| if (std.math.cast(i32, @as(i64, @bitCast(addr))) != null and | 173017 | .memory => |addr| if (std.math.cast(i32, @as(i64, @bitCast(addr))) != null and |
| 172960 | std.math.cast(i32, @as(i64, @bitCast(addr)) + abi_size - limb_abi_size) != null) | 173018 | std.math.cast(i32, @as(i64, @bitCast(addr)) + abi_size - limb_abi_size) != null) |
| ... | @@ -173093,6 +173151,8 @@ fn genBinOpMir( | ... | @@ -173093,6 +173151,8 @@ fn genBinOpMir( |
| 173093 | .indirect, | 173151 | .indirect, |
| 173094 | .load_symbol, | 173152 | .load_symbol, |
| 173095 | .lea_symbol, | 173153 | .lea_symbol, |
| 173154 | .load_pcrel, | ||
| 173155 | .lea_pcrel, | ||
| 173096 | .load_direct, | 173156 | .load_direct, |
| 173097 | .lea_direct, | 173157 | .lea_direct, |
| 173098 | .load_got, | 173158 | .load_got, |
| ... | @@ -173160,6 +173220,7 @@ fn genIntMulComplexOpMir(self: *CodeGen, dst_ty: Type, dst_mcv: MCValue, src_mcv | ... | @@ -173160,6 +173220,7 @@ fn genIntMulComplexOpMir(self: *CodeGen, dst_ty: Type, dst_mcv: MCValue, src_mcv |
| 173160 | .register_overflow, | 173220 | .register_overflow, |
| 173161 | .register_mask, | 173221 | .register_mask, |
| 173162 | .lea_symbol, | 173222 | .lea_symbol, |
| 173223 | .lea_pcrel, | ||
| 173163 | .lea_direct, | 173224 | .lea_direct, |
| 173164 | .lea_got, | 173225 | .lea_got, |
| 173165 | .lea_frame, | 173226 | .lea_frame, |
| ... | @@ -173222,6 +173283,8 @@ fn genIntMulComplexOpMir(self: *CodeGen, dst_ty: Type, dst_mcv: MCValue, src_mcv | ... | @@ -173222,6 +173283,8 @@ fn genIntMulComplexOpMir(self: *CodeGen, dst_ty: Type, dst_mcv: MCValue, src_mcv |
| 173222 | .eflags, | 173283 | .eflags, |
| 173223 | .load_symbol, | 173284 | .load_symbol, |
| 173224 | .lea_symbol, | 173285 | .lea_symbol, |
| 173286 | .load_pcrel, | ||
| 173287 | .lea_pcrel, | ||
| 173225 | .load_direct, | 173288 | .load_direct, |
| 173226 | .lea_direct, | 173289 | .lea_direct, |
| 173227 | .load_got, | 173290 | .load_got, |
| ... | @@ -173281,7 +173344,7 @@ fn genIntMulComplexOpMir(self: *CodeGen, dst_ty: Type, dst_mcv: MCValue, src_mcv | ... | @@ -173281,7 +173344,7 @@ fn genIntMulComplexOpMir(self: *CodeGen, dst_ty: Type, dst_mcv: MCValue, src_mcv |
| 173281 | } | 173344 | } |
| 173282 | }, | 173345 | }, |
| 173283 | .register_pair, .register_triple, .register_quadruple => unreachable, // unimplemented | 173346 | .register_pair, .register_triple, .register_quadruple => unreachable, // unimplemented |
| 173284 | .memory, .indirect, .load_symbol, .load_direct, .load_got, .load_frame => { | 173347 | .memory, .indirect, .load_symbol, .load_pcrel, .load_direct, .load_got, .load_frame => { |
| 173285 | const tmp_reg = try self.copyToTmpRegister(dst_ty, dst_mcv); | 173348 | const tmp_reg = try self.copyToTmpRegister(dst_ty, dst_mcv); |
| 173286 | const tmp_mcv = MCValue{ .register = tmp_reg }; | 173349 | const tmp_mcv = MCValue{ .register = tmp_reg }; |
| 173287 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); | 173350 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| ... | @@ -173450,7 +173513,8 @@ fn genLocalDebugInfo( | ... | @@ -173450,7 +173513,8 @@ fn genLocalDebugInfo( |
| 173450 | .disp = frame_addr.off, | 173513 | .disp = frame_addr.off, |
| 173451 | } }, | 173514 | } }, |
| 173452 | }), | 173515 | }), |
| 173453 | .lea_symbol => |sym_off| try self.asmAirMemory(.dbg_local, inst, .{ | 173516 | // debug info should explicitly ignore pcrel requirements |
| 173517 | .lea_symbol, .lea_pcrel => |sym_off| try self.asmAirMemory(.dbg_local, inst, .{ | ||
| 173454 | .base = .{ .reloc = sym_off.sym_index }, | 173518 | .base = .{ .reloc = sym_off.sym_index }, |
| 173455 | .mod = .{ .rm = .{ | 173519 | .mod = .{ .rm = .{ |
| 173456 | .size = .qword, | 173520 | .size = .qword, |
| ... | @@ -174108,12 +174172,13 @@ fn airCmp(self: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) !v | ... | @@ -174108,12 +174172,13 @@ fn airCmp(self: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) !v |
| 174108 | .lea_got, | 174172 | .lea_got, |
| 174109 | .lea_frame, | 174173 | .lea_frame, |
| 174110 | .lea_symbol, | 174174 | .lea_symbol, |
| 174175 | .lea_pcrel, | ||
| 174111 | .elementwise_args, | 174176 | .elementwise_args, |
| 174112 | .reserved_frame, | 174177 | .reserved_frame, |
| 174113 | .air_ref, | 174178 | .air_ref, |
| 174114 | => unreachable, | 174179 | => unreachable, |
| 174115 | .register, .register_pair, .register_triple, .register_quadruple, .load_frame => null, | 174180 | .register, .register_pair, .register_triple, .register_quadruple, .load_frame => null, |
| 174116 | .memory, .load_symbol, .load_got, .load_direct => dst: { | 174181 | .memory, .load_symbol, .load_pcrel, .load_got, .load_direct => dst: { |
| 174117 | switch (resolved_dst_mcv) { | 174182 | switch (resolved_dst_mcv) { |
| 174118 | .memory => |addr| if (std.math.cast( | 174183 | .memory => |addr| if (std.math.cast( |
| 174119 | i32, | 174184 | i32, |
| ... | @@ -174122,7 +174187,7 @@ fn airCmp(self: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) !v | ... | @@ -174122,7 +174187,7 @@ fn airCmp(self: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) !v |
| 174122 | i32, | 174187 | i32, |
| 174123 | @as(i64, @bitCast(addr)) + abi_size - 8, | 174188 | @as(i64, @bitCast(addr)) + abi_size - 8, |
| 174124 | ) != null) break :dst null, | 174189 | ) != null) break :dst null, |
| 174125 | .load_symbol, .load_got, .load_direct => {}, | 174190 | .load_symbol, .load_pcrel, .load_got, .load_direct => {}, |
| 174126 | else => unreachable, | 174191 | else => unreachable, |
| 174127 | } | 174192 | } |
| 174128 | 174193 | ||
| ... | @@ -174160,6 +174225,7 @@ fn airCmp(self: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) !v | ... | @@ -174160,6 +174225,7 @@ fn airCmp(self: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) !v |
| 174160 | .register_mask, | 174225 | .register_mask, |
| 174161 | .indirect, | 174226 | .indirect, |
| 174162 | .lea_symbol, | 174227 | .lea_symbol, |
| 174228 | .lea_pcrel, | ||
| 174163 | .lea_direct, | 174229 | .lea_direct, |
| 174164 | .lea_got, | 174230 | .lea_got, |
| 174165 | .lea_frame, | 174231 | .lea_frame, |
| ... | @@ -174168,7 +174234,7 @@ fn airCmp(self: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) !v | ... | @@ -174168,7 +174234,7 @@ fn airCmp(self: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) !v |
| 174168 | .air_ref, | 174234 | .air_ref, |
| 174169 | => unreachable, | 174235 | => unreachable, |
| 174170 | .register_pair, .register_triple, .register_quadruple, .load_frame => null, | 174236 | .register_pair, .register_triple, .register_quadruple, .load_frame => null, |
| 174171 | .memory, .load_symbol, .load_got, .load_direct => src: { | 174237 | .memory, .load_symbol, .load_pcrel, .load_got, .load_direct => src: { |
| 174172 | switch (resolved_src_mcv) { | 174238 | switch (resolved_src_mcv) { |
| 174173 | .memory => |addr| if (std.math.cast( | 174239 | .memory => |addr| if (std.math.cast( |
| 174174 | i32, | 174240 | i32, |
| ... | @@ -174177,7 +174243,7 @@ fn airCmp(self: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) !v | ... | @@ -174177,7 +174243,7 @@ fn airCmp(self: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) !v |
| 174177 | i32, | 174243 | i32, |
| 174178 | @as(i64, @bitCast(addr)) + abi_size - 8, | 174244 | @as(i64, @bitCast(addr)) + abi_size - 8, |
| 174179 | ) != null) break :src null, | 174245 | ) != null) break :src null, |
| 174180 | .load_symbol, .load_got, .load_direct => {}, | 174246 | .load_symbol, .load_pcrel, .load_got, .load_direct => {}, |
| 174181 | else => unreachable, | 174247 | else => unreachable, |
| 174182 | } | 174248 | } |
| 174183 | 174249 | ||
| ... | @@ -174568,6 +174634,7 @@ fn isNull(self: *CodeGen, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) | ... | @@ -174568,6 +174634,7 @@ fn isNull(self: *CodeGen, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) |
| 174568 | .lea_direct, | 174634 | .lea_direct, |
| 174569 | .lea_got, | 174635 | .lea_got, |
| 174570 | .lea_symbol, | 174636 | .lea_symbol, |
| 174637 | .lea_pcrel, | ||
| 174571 | .elementwise_args, | 174638 | .elementwise_args, |
| 174572 | .reserved_frame, | 174639 | .reserved_frame, |
| 174573 | .air_ref, | 174640 | .air_ref, |
| ... | @@ -174616,6 +174683,7 @@ fn isNull(self: *CodeGen, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) | ... | @@ -174616,6 +174683,7 @@ fn isNull(self: *CodeGen, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) |
| 174616 | 174683 | ||
| 174617 | .memory, | 174684 | .memory, |
| 174618 | .load_symbol, | 174685 | .load_symbol, |
| 174686 | .load_pcrel, | ||
| 174619 | .load_got, | 174687 | .load_got, |
| 174620 | .load_direct, | 174688 | .load_direct, |
| 174621 | => { | 174689 | => { |
| ... | @@ -176625,6 +176693,7 @@ fn genCopy(self: *CodeGen, ty: Type, dst_mcv: MCValue, src_mcv: MCValue, opts: C | ... | @@ -176625,6 +176693,7 @@ fn genCopy(self: *CodeGen, ty: Type, dst_mcv: MCValue, src_mcv: MCValue, opts: C |
| 176625 | .lea_got, | 176693 | .lea_got, |
| 176626 | .lea_frame, | 176694 | .lea_frame, |
| 176627 | .lea_symbol, | 176695 | .lea_symbol, |
| 176696 | .lea_pcrel, | ||
| 176628 | .elementwise_args, | 176697 | .elementwise_args, |
| 176629 | .reserved_frame, | 176698 | .reserved_frame, |
| 176630 | .air_ref, | 176699 | .air_ref, |
| ... | @@ -176719,7 +176788,7 @@ fn genCopy(self: *CodeGen, ty: Type, dst_mcv: MCValue, src_mcv: MCValue, opts: C | ... | @@ -176719,7 +176788,7 @@ fn genCopy(self: *CodeGen, ty: Type, dst_mcv: MCValue, src_mcv: MCValue, opts: C |
| 176719 | } | 176788 | } |
| 176720 | return; | 176789 | return; |
| 176721 | }, | 176790 | }, |
| 176722 | .load_symbol, .load_direct, .load_got => { | 176791 | .load_symbol, .load_pcrel, .load_direct, .load_got => { |
| 176723 | const src_addr_reg = | 176792 | const src_addr_reg = |
| 176724 | (try self.register_manager.allocReg(null, abi.RegisterClass.gp)).to64(); | 176793 | (try self.register_manager.allocReg(null, abi.RegisterClass.gp)).to64(); |
| 176725 | const src_addr_lock = self.register_manager.lockRegAssumeUnused(src_addr_reg); | 176794 | const src_addr_lock = self.register_manager.lockRegAssumeUnused(src_addr_reg); |
| ... | @@ -176752,7 +176821,7 @@ fn genCopy(self: *CodeGen, ty: Type, dst_mcv: MCValue, src_mcv: MCValue, opts: C | ... | @@ -176752,7 +176821,7 @@ fn genCopy(self: *CodeGen, ty: Type, dst_mcv: MCValue, src_mcv: MCValue, opts: C |
| 176752 | .undef => if (opts.safety and part_i > 0) .{ .register = dst_regs[0] } else .undef, | 176821 | .undef => if (opts.safety and part_i > 0) .{ .register = dst_regs[0] } else .undef, |
| 176753 | dst_tag => |src_regs| .{ .register = src_regs[part_i] }, | 176822 | dst_tag => |src_regs| .{ .register = src_regs[part_i] }, |
| 176754 | .memory, .indirect, .load_frame => src_mcv.address().offset(part_disp).deref(), | 176823 | .memory, .indirect, .load_frame => src_mcv.address().offset(part_disp).deref(), |
| 176755 | .load_symbol, .load_direct, .load_got => .{ .indirect = .{ | 176824 | .load_symbol, .load_pcrel, .load_direct, .load_got => .{ .indirect = .{ |
| 176756 | .reg = src_info.?.addr_reg, | 176825 | .reg = src_info.?.addr_reg, |
| 176757 | .off = part_disp, | 176826 | .off = part_disp, |
| 176758 | } }, | 176827 | } }, |
| ... | @@ -176773,11 +176842,11 @@ fn genCopy(self: *CodeGen, ty: Type, dst_mcv: MCValue, src_mcv: MCValue, opts: C | ... | @@ -176773,11 +176842,11 @@ fn genCopy(self: *CodeGen, ty: Type, dst_mcv: MCValue, src_mcv: MCValue, opts: C |
| 176773 | src_mcv, | 176842 | src_mcv, |
| 176774 | opts, | 176843 | opts, |
| 176775 | ), | 176844 | ), |
| 176776 | .memory, .load_symbol, .load_direct, .load_got => { | 176845 | .memory, .load_symbol, .load_pcrel, .load_direct, .load_got => { |
| 176777 | switch (dst_mcv) { | 176846 | switch (dst_mcv) { |
| 176778 | .memory => |addr| if (std.math.cast(i32, @as(i64, @bitCast(addr)))) |small_addr| | 176847 | .memory => |addr| if (std.math.cast(i32, @as(i64, @bitCast(addr)))) |small_addr| |
| 176779 | return self.genSetMem(.{ .reg = .ds }, small_addr, ty, src_mcv, opts), | 176848 | return self.genSetMem(.{ .reg = .ds }, small_addr, ty, src_mcv, opts), |
| 176780 | .load_symbol, .load_direct, .load_got => {}, | 176849 | .load_symbol, .load_pcrel, .load_direct, .load_got => {}, |
| 176781 | else => unreachable, | 176850 | else => unreachable, |
| 176782 | } | 176851 | } |
| 176783 | 176852 | ||
| ... | @@ -177234,7 +177303,7 @@ fn genSetReg( | ... | @@ -177234,7 +177303,7 @@ fn genSetReg( |
| 177234 | if (src_reg_mask.info.inverted) try self.asmRegister(.{ ._, .not }, registerAlias(bits_reg, abi_size)); | 177303 | if (src_reg_mask.info.inverted) try self.asmRegister(.{ ._, .not }, registerAlias(bits_reg, abi_size)); |
| 177235 | try self.genSetReg(dst_reg, ty, .{ .register = bits_reg }, .{}); | 177304 | try self.genSetReg(dst_reg, ty, .{ .register = bits_reg }, .{}); |
| 177236 | }, | 177305 | }, |
| 177237 | .memory, .load_symbol, .load_direct, .load_got => { | 177306 | .memory, .load_symbol, .load_pcrel, .load_direct, .load_got => { |
| 177238 | switch (src_mcv) { | 177307 | switch (src_mcv) { |
| 177239 | .memory => |addr| if (std.math.cast(i32, @as(i64, @bitCast(addr)))) |small_addr| | 177308 | .memory => |addr| if (std.math.cast(i32, @as(i64, @bitCast(addr)))) |small_addr| |
| 177240 | return (try self.moveStrategy( | 177309 | return (try self.moveStrategy( |
| ... | @@ -177263,6 +177332,21 @@ fn genSetReg( | ... | @@ -177263,6 +177332,21 @@ fn genSetReg( |
| 177263 | .segment, .mmx, .ip, .cr, .dr => unreachable, | 177332 | .segment, .mmx, .ip, .cr, .dr => unreachable, |
| 177264 | .x87, .sse => {}, | 177333 | .x87, .sse => {}, |
| 177265 | }, | 177334 | }, |
| 177335 | .load_pcrel => |sym_off| switch (dst_reg.class()) { | ||
| 177336 | .general_purpose, .gphi => { | ||
| 177337 | assert(sym_off.off == 0); | ||
| 177338 | try self.asmRegisterMemory(.{ ._, .mov }, dst_alias, .{ | ||
| 177339 | .base = .{ .pcrel = sym_off.sym_index }, | ||
| 177340 | .mod = .{ .rm = .{ | ||
| 177341 | .size = self.memSize(ty), | ||
| 177342 | .disp = sym_off.off, | ||
| 177343 | } }, | ||
| 177344 | }); | ||
| 177345 | return; | ||
| 177346 | }, | ||
| 177347 | .segment, .mmx, .ip, .cr, .dr => unreachable, | ||
| 177348 | .x87, .sse => {}, | ||
| 177349 | }, | ||
| 177266 | .load_direct => |sym_index| switch (dst_reg.class()) { | 177350 | .load_direct => |sym_index| switch (dst_reg.class()) { |
| 177267 | .general_purpose, .gphi => { | 177351 | .general_purpose, .gphi => { |
| 177268 | _ = try self.addInst(.{ | 177352 | _ = try self.addInst(.{ |
| ... | @@ -177313,6 +177397,28 @@ fn genSetReg( | ... | @@ -177313,6 +177397,28 @@ fn genSetReg( |
| 177313 | @tagName(self.bin_file.tag), | 177397 | @tagName(self.bin_file.tag), |
| 177314 | }), | 177398 | }), |
| 177315 | }, | 177399 | }, |
| 177400 | .lea_pcrel => |sym_off| switch (self.bin_file.tag) { | ||
| 177401 | .elf, .macho => { | ||
| 177402 | try self.asmRegisterMemory( | ||
| 177403 | .{ ._, .lea }, | ||
| 177404 | dst_reg.to64(), | ||
| 177405 | .{ | ||
| 177406 | .base = .{ .pcrel = sym_off.sym_index }, | ||
| 177407 | }, | ||
| 177408 | ); | ||
| 177409 | if (sym_off.off != 0) try self.asmRegisterMemory( | ||
| 177410 | .{ ._, .lea }, | ||
| 177411 | dst_reg.to64(), | ||
| 177412 | .{ | ||
| 177413 | .base = .{ .reg = dst_reg.to64() }, | ||
| 177414 | .mod = .{ .rm = .{ .disp = sym_off.off } }, | ||
| 177415 | }, | ||
| 177416 | ); | ||
| 177417 | }, | ||
| 177418 | else => return self.fail("TODO emit symbol sequence on {s}", .{ | ||
| 177419 | @tagName(self.bin_file.tag), | ||
| 177420 | }), | ||
| 177421 | }, | ||
| 177316 | .lea_direct, .lea_got => |sym_index| _ = try self.addInst(.{ | 177422 | .lea_direct, .lea_got => |sym_index| _ = try self.addInst(.{ |
| 177317 | .tag = switch (src_mcv) { | 177423 | .tag = switch (src_mcv) { |
| 177318 | .lea_direct => .lea, | 177424 | .lea_direct => .lea, |
| ... | @@ -177350,6 +177456,7 @@ fn genSetMem( | ... | @@ -177350,6 +177456,7 @@ fn genSetMem( |
| 177350 | .frame => |base_frame_index| .{ .lea_frame = .{ .index = base_frame_index, .off = disp } }, | 177456 | .frame => |base_frame_index| .{ .lea_frame = .{ .index = base_frame_index, .off = disp } }, |
| 177351 | .table, .rip_inst => unreachable, | 177457 | .table, .rip_inst => unreachable, |
| 177352 | .reloc => |sym_index| .{ .lea_symbol = .{ .sym_index = sym_index, .off = disp } }, | 177458 | .reloc => |sym_index| .{ .lea_symbol = .{ .sym_index = sym_index, .off = disp } }, |
| 177459 | .pcrel => |sym_index| .{ .lea_pcrel = .{ .sym_index = sym_index, .off = disp } }, | ||
| 177353 | }; | 177460 | }; |
| 177354 | switch (src_mcv) { | 177461 | switch (src_mcv) { |
| 177355 | .none, | 177462 | .none, |
| ... | @@ -177466,7 +177573,7 @@ fn genSetMem( | ... | @@ -177466,7 +177573,7 @@ fn genSetMem( |
| 177466 | .off = disp, | 177573 | .off = disp, |
| 177467 | }).compare(.gte, src_align), | 177574 | }).compare(.gte, src_align), |
| 177468 | .table, .rip_inst => unreachable, | 177575 | .table, .rip_inst => unreachable, |
| 177469 | .reloc => false, | 177576 | .reloc, .pcrel => false, |
| 177470 | })).write( | 177577 | })).write( |
| 177471 | self, | 177578 | self, |
| 177472 | .{ .base = base, .mod = .{ .rm = .{ | 177579 | .{ .base = base, .mod = .{ .rm = .{ |
| ... | @@ -177557,6 +177664,8 @@ fn genSetMem( | ... | @@ -177557,6 +177664,8 @@ fn genSetMem( |
| 177557 | .lea_frame, | 177664 | .lea_frame, |
| 177558 | .load_symbol, | 177665 | .load_symbol, |
| 177559 | .lea_symbol, | 177666 | .lea_symbol, |
| 177667 | .load_pcrel, | ||
| 177668 | .lea_pcrel, | ||
| 177560 | => switch (abi_size) { | 177669 | => switch (abi_size) { |
| 177561 | 0 => {}, | 177670 | 0 => {}, |
| 177562 | 1, 2, 4, 8 => { | 177671 | 1, 2, 4, 8 => { |
| ... | @@ -178110,7 +178219,7 @@ fn airCmpxchg(self: *CodeGen, inst: Air.Inst.Index) !void { | ... | @@ -178110,7 +178219,7 @@ fn airCmpxchg(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 178110 | .off => return self.fail("TODO airCmpxchg with {s}", .{@tagName(ptr_mcv)}), | 178219 | .off => return self.fail("TODO airCmpxchg with {s}", .{@tagName(ptr_mcv)}), |
| 178111 | } | 178220 | } |
| 178112 | const ptr_lock = switch (ptr_mem.base) { | 178221 | const ptr_lock = switch (ptr_mem.base) { |
| 178113 | .none, .frame, .reloc => null, | 178222 | .none, .frame, .reloc, .pcrel => null, |
| 178114 | .reg => |reg| self.register_manager.lockReg(reg), | 178223 | .reg => |reg| self.register_manager.lockReg(reg), |
| 178115 | .table, .rip_inst => unreachable, | 178224 | .table, .rip_inst => unreachable, |
| 178116 | }; | 178225 | }; |
| ... | @@ -178193,7 +178302,7 @@ fn atomicOp( | ... | @@ -178193,7 +178302,7 @@ fn atomicOp( |
| 178193 | .off => return self.fail("TODO airCmpxchg with {s}", .{@tagName(ptr_mcv)}), | 178302 | .off => return self.fail("TODO airCmpxchg with {s}", .{@tagName(ptr_mcv)}), |
| 178194 | } | 178303 | } |
| 178195 | const mem_lock = switch (ptr_mem.base) { | 178304 | const mem_lock = switch (ptr_mem.base) { |
| 178196 | .none, .frame, .reloc => null, | 178305 | .none, .frame, .reloc, .pcrel => null, |
| 178197 | .reg => |reg| self.register_manager.lockReg(reg), | 178306 | .reg => |reg| self.register_manager.lockReg(reg), |
| 178198 | .table, .rip_inst => unreachable, | 178307 | .table, .rip_inst => unreachable, |
| 178199 | }; | 178308 | }; |
| ... | @@ -182266,6 +182375,8 @@ const Temp = struct { | ... | @@ -182266,6 +182375,8 @@ const Temp = struct { |
| 182266 | .memory, | 182375 | .memory, |
| 182267 | .load_symbol, | 182376 | .load_symbol, |
| 182268 | .lea_symbol, | 182377 | .lea_symbol, |
| 182378 | .load_pcrel, | ||
| 182379 | .lea_pcrel, | ||
| 182269 | .indirect, | 182380 | .indirect, |
| 182270 | .load_direct, | 182381 | .load_direct, |
| 182271 | .lea_direct, | 182382 | .lea_direct, |
| ... | @@ -182427,6 +182538,22 @@ const Temp = struct { | ... | @@ -182427,6 +182538,22 @@ const Temp = struct { |
| 182427 | assert(limb_index == 0); | 182538 | assert(limb_index == 0); |
| 182428 | new_temp_index.tracking(cg).* = .init(.{ .lea_symbol = sym_off }); | 182539 | new_temp_index.tracking(cg).* = .init(.{ .lea_symbol = sym_off }); |
| 182429 | }, | 182540 | }, |
| 182541 | .load_pcrel => |sym_off| { | ||
| 182542 | const new_reg = | ||
| 182543 | try cg.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp); | ||
| 182544 | new_temp_index.tracking(cg).* = .init(.{ .register = new_reg }); | ||
| 182545 | try cg.asmRegisterMemory(.{ ._, .mov }, new_reg.to64(), .{ | ||
| 182546 | .base = .{ .pcrel = sym_off.sym_index }, | ||
| 182547 | .mod = .{ .rm = .{ | ||
| 182548 | .size = .qword, | ||
| 182549 | .disp = sym_off.off + @as(u31, limb_index) * 8, | ||
| 182550 | } }, | ||
| 182551 | }); | ||
| 182552 | }, | ||
| 182553 | .lea_pcrel => |sym_off| { | ||
| 182554 | assert(limb_index == 0); | ||
| 182555 | new_temp_index.tracking(cg).* = .init(.{ .lea_pcrel = sym_off }); | ||
| 182556 | }, | ||
| 182430 | .load_frame => |frame_addr| { | 182557 | .load_frame => |frame_addr| { |
| 182431 | const new_reg = | 182558 | const new_reg = |
| 182432 | try cg.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp); | 182559 | try cg.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp); |
| ... | @@ -182721,11 +182848,12 @@ const Temp = struct { | ... | @@ -182721,11 +182848,12 @@ const Temp = struct { |
| 182721 | .memory, | 182848 | .memory, |
| 182722 | .indirect, | 182849 | .indirect, |
| 182723 | .load_symbol, | 182850 | .load_symbol, |
| 182851 | .load_pcrel, | ||
| 182724 | .load_direct, | 182852 | .load_direct, |
| 182725 | .load_got, | 182853 | .load_got, |
| 182726 | .load_frame, | 182854 | .load_frame, |
| 182727 | => return temp.toRegClass(true, .general_purpose, cg), | 182855 | => return temp.toRegClass(true, .general_purpose, cg), |
| 182728 | .lea_symbol => |sym_off| { | 182856 | .lea_symbol, .lea_pcrel => |sym_off| { |
| 182729 | const off = sym_off.off; | 182857 | const off = sym_off.off; |
| 182730 | // hack around linker relocation bugs | 182858 | // hack around linker relocation bugs |
| 182731 | if (false and off == 0) return false; | 182859 | if (false and off == 0) return false; |
| ... | @@ -187464,6 +187592,8 @@ const Temp = struct { | ... | @@ -187464,6 +187592,8 @@ const Temp = struct { |
| 187464 | .memory, | 187592 | .memory, |
| 187465 | .load_symbol, | 187593 | .load_symbol, |
| 187466 | .lea_symbol, | 187594 | .lea_symbol, |
| 187595 | .load_pcrel, | ||
| 187596 | .lea_pcrel, | ||
| 187467 | .indirect, | 187597 | .indirect, |
| 187468 | .load_direct, | 187598 | .load_direct, |
| 187469 | .lea_direct, | 187599 | .lea_direct, |
| ... | @@ -190044,6 +190174,7 @@ const Select = struct { | ... | @@ -190044,6 +190174,7 @@ const Select = struct { |
| 190044 | .register => |base_reg| .{ .reg = base_reg.toSize(.ptr, s.cg.target) }, | 190174 | .register => |base_reg| .{ .reg = base_reg.toSize(.ptr, s.cg.target) }, |
| 190045 | .register_offset => |base_reg_off| .{ .reg = base_reg_off.reg.toSize(.ptr, s.cg.target) }, | 190175 | .register_offset => |base_reg_off| .{ .reg = base_reg_off.reg.toSize(.ptr, s.cg.target) }, |
| 190046 | .lea_symbol => |base_sym_off| .{ .reloc = base_sym_off.sym_index }, | 190176 | .lea_symbol => |base_sym_off| .{ .reloc = base_sym_off.sym_index }, |
| 190177 | .lea_pcrel => |base_sym_off| .{ .pcrel = base_sym_off.sym_index }, | ||
| 190047 | }, | 190178 | }, |
| 190048 | .mod = .{ .rm = .{ | 190179 | .mod = .{ .rm = .{ |
| 190049 | .size = op.flags.base.size, | 190180 | .size = op.flags.base.size, |
src/arch/x86_64/Emit.zig+4-3| ... | @@ -189,12 +189,12 @@ pub fn emitMir(emit: *Emit) Error!void { | ... | @@ -189,12 +189,12 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 189 | .r_addend = lowered_relocs[0].off, | 189 | .r_addend = lowered_relocs[0].off, |
| 190 | }, zo); | 190 | }, zo); |
| 191 | }, | 191 | }, |
| 192 | .linker_reloc => |sym_index| if (emit.lower.bin_file.cast(.elf)) |elf_file| { | 192 | .linker_reloc, .linker_pcrel => |sym_index| if (emit.lower.bin_file.cast(.elf)) |elf_file| { |
| 193 | const zo = elf_file.zigObjectPtr().?; | 193 | const zo = elf_file.zigObjectPtr().?; |
| 194 | const atom = zo.symbol(emit.atom_index).atom(elf_file).?; | 194 | const atom = zo.symbol(emit.atom_index).atom(elf_file).?; |
| 195 | const sym = zo.symbol(sym_index); | 195 | const sym = zo.symbol(sym_index); |
| 196 | if (emit.lower.pic) { | 196 | if (emit.lower.pic) { |
| 197 | const r_type: u32 = if (sym.flags.is_extern_ptr) | 197 | const r_type: u32 = if (sym.flags.is_extern_ptr and lowered_relocs[0].target != .linker_pcrel) |
| 198 | @intFromEnum(std.elf.R_X86_64.GOTPCREL) | 198 | @intFromEnum(std.elf.R_X86_64.GOTPCREL) |
| 199 | else | 199 | else |
| 200 | @intFromEnum(std.elf.R_X86_64.PC32); | 200 | @intFromEnum(std.elf.R_X86_64.PC32); |
| ... | @@ -218,7 +218,7 @@ pub fn emitMir(emit: *Emit) Error!void { | ... | @@ -218,7 +218,7 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 218 | const zo = macho_file.getZigObject().?; | 218 | const zo = macho_file.getZigObject().?; |
| 219 | const atom = zo.symbols.items[emit.atom_index].getAtom(macho_file).?; | 219 | const atom = zo.symbols.items[emit.atom_index].getAtom(macho_file).?; |
| 220 | const sym = &zo.symbols.items[sym_index]; | 220 | const sym = &zo.symbols.items[sym_index]; |
| 221 | const @"type": link.File.MachO.Relocation.Type = if (sym.flags.is_extern_ptr) | 221 | const @"type": link.File.MachO.Relocation.Type = if (sym.flags.is_extern_ptr and lowered_relocs[0].target != .linker_pcrel) |
| 222 | .got_load | 222 | .got_load |
| 223 | else if (sym.flags.tlv) | 223 | else if (sym.flags.tlv) |
| 224 | .tlv | 224 | .tlv |
| ... | @@ -438,6 +438,7 @@ pub fn emitMir(emit: *Emit) Error!void { | ... | @@ -438,6 +438,7 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 438 | .reg => |reg| .{ .breg = reg.dwarfNum() }, | 438 | .reg => |reg| .{ .breg = reg.dwarfNum() }, |
| 439 | .frame, .table, .rip_inst => unreachable, | 439 | .frame, .table, .rip_inst => unreachable, |
| 440 | .reloc => |sym_index| .{ .addr_reloc = sym_index }, | 440 | .reloc => |sym_index| .{ .addr_reloc = sym_index }, |
| 441 | .pcrel => unreachable, | ||
| 441 | }; | 442 | }; |
| 442 | break :base &loc_buf[0]; | 443 | break :base &loc_buf[0]; |
| 443 | }, | 444 | }, |
src/arch/x86_64/Lower.zig+19-2| ... | @@ -66,6 +66,7 @@ pub const Reloc = struct { | ... | @@ -66,6 +66,7 @@ pub const Reloc = struct { |
| 66 | inst: Mir.Inst.Index, | 66 | inst: Mir.Inst.Index, |
| 67 | table, | 67 | table, |
| 68 | linker_reloc: u32, | 68 | linker_reloc: u32, |
| 69 | linker_pcrel: u32, | ||
| 69 | linker_tlsld: u32, | 70 | linker_tlsld: u32, |
| 70 | linker_dtpoff: u32, | 71 | linker_dtpoff: u32, |
| 71 | linker_extern_fn: u32, | 72 | linker_extern_fn: u32, |
| ... | @@ -421,9 +422,9 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand) | ... | @@ -421,9 +422,9 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand) |
| 421 | for (emit_ops, ops, 0..) |*emit_op, op, op_index| { | 422 | for (emit_ops, ops, 0..) |*emit_op, op, op_index| { |
| 422 | emit_op.* = switch (op) { | 423 | emit_op.* = switch (op) { |
| 423 | else => op, | 424 | else => op, |
| 424 | .mem => |mem_op| switch (mem_op.base()) { | 425 | .mem => |mem_op| op: switch (mem_op.base()) { |
| 425 | else => op, | 426 | else => op, |
| 426 | .reloc => |sym_index| op: { | 427 | .reloc => |sym_index| { |
| 427 | assert(prefix == .none); | 428 | assert(prefix == .none); |
| 428 | assert(mem_op.sib.disp == 0); | 429 | assert(mem_op.sib.disp == 0); |
| 429 | assert(mem_op.sib.scale_index.scale == 0); | 430 | assert(mem_op.sib.scale_index.scale == 0); |
| ... | @@ -559,6 +560,22 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand) | ... | @@ -559,6 +560,22 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand) |
| 559 | return lower.fail("TODO: bin format '{s}'", .{@tagName(lower.bin_file.tag)}); | 560 | return lower.fail("TODO: bin format '{s}'", .{@tagName(lower.bin_file.tag)}); |
| 560 | } | 561 | } |
| 561 | }, | 562 | }, |
| 563 | .pcrel => |sym_index| { | ||
| 564 | assert(prefix == .none); | ||
| 565 | assert(mem_op.sib.disp == 0); | ||
| 566 | assert(mem_op.sib.scale_index.scale == 0); | ||
| 567 | |||
| 568 | _ = lower.reloc(@intCast(op_index), .{ .linker_pcrel = sym_index }, 0); | ||
| 569 | break :op switch (lower.bin_file.tag) { | ||
| 570 | .elf => op, | ||
| 571 | .macho => switch (mnemonic) { | ||
| 572 | .lea => .{ .mem = Memory.initRip(.none, 0) }, | ||
| 573 | .mov => .{ .mem = Memory.initRip(mem_op.sib.ptr_size, 0) }, | ||
| 574 | else => unreachable, | ||
| 575 | }, | ||
| 576 | else => |tag| return lower.fail("TODO: bin format '{s}'", .{@tagName(tag)}), | ||
| 577 | }; | ||
| 578 | }, | ||
| 562 | }, | 579 | }, |
| 563 | }; | 580 | }; |
| 564 | } | 581 | } |
src/arch/x86_64/Mir.zig+3-2| ... | @@ -1866,7 +1866,7 @@ pub const Memory = struct { | ... | @@ -1866,7 +1866,7 @@ pub const Memory = struct { |
| 1866 | .none, .table => undefined, | 1866 | .none, .table => undefined, |
| 1867 | .reg => |reg| @intFromEnum(reg), | 1867 | .reg => |reg| @intFromEnum(reg), |
| 1868 | .frame => |frame_index| @intFromEnum(frame_index), | 1868 | .frame => |frame_index| @intFromEnum(frame_index), |
| 1869 | .reloc => |sym_index| sym_index, | 1869 | .reloc, .pcrel => |sym_index| sym_index, |
| 1870 | .rip_inst => |inst_index| inst_index, | 1870 | .rip_inst => |inst_index| inst_index, |
| 1871 | }, | 1871 | }, |
| 1872 | .off = switch (mem.mod) { | 1872 | .off = switch (mem.mod) { |
| ... | @@ -1895,6 +1895,7 @@ pub const Memory = struct { | ... | @@ -1895,6 +1895,7 @@ pub const Memory = struct { |
| 1895 | .frame => .{ .frame = @enumFromInt(mem.base) }, | 1895 | .frame => .{ .frame = @enumFromInt(mem.base) }, |
| 1896 | .table => .table, | 1896 | .table => .table, |
| 1897 | .reloc => .{ .reloc = mem.base }, | 1897 | .reloc => .{ .reloc = mem.base }, |
| 1898 | .pcrel => .{ .pcrel = mem.base }, | ||
| 1898 | .rip_inst => .{ .rip_inst = mem.base }, | 1899 | .rip_inst => .{ .rip_inst = mem.base }, |
| 1899 | }, | 1900 | }, |
| 1900 | .scale_index = switch (mem.info.index) { | 1901 | .scale_index = switch (mem.info.index) { |
| ... | @@ -1959,7 +1960,7 @@ pub fn resolveFrameAddr(mir: Mir, frame_addr: bits.FrameAddr) bits.RegisterOffse | ... | @@ -1959,7 +1960,7 @@ pub fn resolveFrameAddr(mir: Mir, frame_addr: bits.FrameAddr) bits.RegisterOffse |
| 1959 | 1960 | ||
| 1960 | pub fn resolveFrameLoc(mir: Mir, mem: Memory) Memory { | 1961 | pub fn resolveFrameLoc(mir: Mir, mem: Memory) Memory { |
| 1961 | return switch (mem.info.base) { | 1962 | return switch (mem.info.base) { |
| 1962 | .none, .reg, .table, .reloc, .rip_inst => mem, | 1963 | .none, .reg, .table, .reloc, .pcrel, .rip_inst => mem, |
| 1963 | .frame => if (mir.frame_locs.len > 0) .{ | 1964 | .frame => if (mir.frame_locs.len > 0) .{ |
| 1964 | .info = .{ | 1965 | .info = .{ |
| 1965 | .base = .reg, | 1966 | .base = .reg, |
src/arch/x86_64/bits.zig+1| ... | @@ -762,6 +762,7 @@ pub const Memory = struct { | ... | @@ -762,6 +762,7 @@ pub const Memory = struct { |
| 762 | frame: FrameIndex, | 762 | frame: FrameIndex, |
| 763 | table, | 763 | table, |
| 764 | reloc: u32, | 764 | reloc: u32, |
| 765 | pcrel: u32, | ||
| 765 | rip_inst: Mir.Inst.Index, | 766 | rip_inst: Mir.Inst.Index, |
| 766 | 767 | ||
| 767 | pub const Tag = @typeInfo(Base).@"union".tag_type.?; | 768 | pub const Tag = @typeInfo(Base).@"union".tag_type.?; |
src/arch/x86_64/encoder.zig+4-3| ... | @@ -138,7 +138,7 @@ pub const Instruction = struct { | ... | @@ -138,7 +138,7 @@ pub const Instruction = struct { |
| 138 | .moffs => true, | 138 | .moffs => true, |
| 139 | .rip => false, | 139 | .rip => false, |
| 140 | .sib => |s| switch (s.base) { | 140 | .sib => |s| switch (s.base) { |
| 141 | .none, .frame, .table, .reloc, .rip_inst => false, | 141 | .none, .frame, .table, .reloc, .pcrel, .rip_inst => false, |
| 142 | .reg => |reg| reg.isClass(.segment), | 142 | .reg => |reg| reg.isClass(.segment), |
| 143 | }, | 143 | }, |
| 144 | }; | 144 | }; |
| ... | @@ -211,7 +211,7 @@ pub const Instruction = struct { | ... | @@ -211,7 +211,7 @@ pub const Instruction = struct { |
| 211 | .none, .imm => 0b00, | 211 | .none, .imm => 0b00, |
| 212 | .reg => |reg| @truncate(reg.enc() >> 3), | 212 | .reg => |reg| @truncate(reg.enc() >> 3), |
| 213 | .mem => |mem| switch (mem.base()) { | 213 | .mem => |mem| switch (mem.base()) { |
| 214 | .none, .frame, .table, .reloc, .rip_inst => 0b00, // rsp, rbp, and rip are not extended | 214 | .none, .frame, .table, .reloc, .pcrel, .rip_inst => 0b00, // rsp, rbp, and rip are not extended |
| 215 | .reg => |reg| @truncate(reg.enc() >> 3), | 215 | .reg => |reg| @truncate(reg.enc() >> 3), |
| 216 | }, | 216 | }, |
| 217 | .bytes => unreachable, | 217 | .bytes => unreachable, |
| ... | @@ -282,6 +282,7 @@ pub const Instruction = struct { | ... | @@ -282,6 +282,7 @@ pub const Instruction = struct { |
| 282 | .frame => |frame_index| try writer.print("{}", .{frame_index}), | 282 | .frame => |frame_index| try writer.print("{}", .{frame_index}), |
| 283 | .table => try writer.print("Table", .{}), | 283 | .table => try writer.print("Table", .{}), |
| 284 | .reloc => |sym_index| try writer.print("Symbol({d})", .{sym_index}), | 284 | .reloc => |sym_index| try writer.print("Symbol({d})", .{sym_index}), |
| 285 | .pcrel => |sym_index| try writer.print("PcRelSymbol({d})", .{sym_index}), | ||
| 285 | .rip_inst => |inst_index| try writer.print("RipInst({d})", .{inst_index}), | 286 | .rip_inst => |inst_index| try writer.print("RipInst({d})", .{inst_index}), |
| 286 | } | 287 | } |
| 287 | if (mem.scaleIndex()) |si| { | 288 | if (mem.scaleIndex()) |si| { |
| ... | @@ -721,7 +722,7 @@ pub const Instruction = struct { | ... | @@ -721,7 +722,7 @@ pub const Instruction = struct { |
| 721 | try encoder.modRm_indirectDisp32(operand_enc, 0); | 722 | try encoder.modRm_indirectDisp32(operand_enc, 0); |
| 722 | try encoder.disp32(undefined); | 723 | try encoder.disp32(undefined); |
| 723 | } else return error.CannotEncode, | 724 | } else return error.CannotEncode, |
| 724 | .rip_inst => { | 725 | .pcrel, .rip_inst => { |
| 725 | try encoder.modRm_RIPDisp32(operand_enc); | 726 | try encoder.modRm_RIPDisp32(operand_enc); |
| 726 | try encoder.disp32(sib.disp); | 727 | try encoder.disp32(sib.disp); |
| 727 | }, | 728 | }, |
src/codegen.zig+57-24| ... | @@ -921,41 +921,74 @@ fn genNavRef( | ... | @@ -921,41 +921,74 @@ fn genNavRef( |
| 921 | const nav = ip.getNav(nav_index); | 921 | const nav = ip.getNav(nav_index); |
| 922 | assert(!nav.isThreadlocal(ip)); | 922 | assert(!nav.isThreadlocal(ip)); |
| 923 | 923 | ||
| 924 | const is_extern, const lib_name = if (nav.getExtern(ip)) |e| | 924 | const lib_name, const linkage, const visibility = if (nav.getExtern(ip)) |e| |
| 925 | .{ true, e.lib_name } | 925 | .{ e.lib_name, e.linkage, e.visibility } |
| 926 | else | 926 | else |
| 927 | .{ false, .none }; | 927 | .{ .none, .internal, .default }; |
| 928 | 928 | ||
| 929 | const name = nav.name; | 929 | const name = nav.name; |
| 930 | if (lf.cast(.elf)) |elf_file| { | 930 | if (lf.cast(.elf)) |elf_file| { |
| 931 | const zo = elf_file.zigObjectPtr().?; | 931 | const zo = elf_file.zigObjectPtr().?; |
| 932 | if (is_extern) { | 932 | switch (linkage) { |
| 933 | const sym_index = try elf_file.getGlobalSymbol(name.toSlice(ip), lib_name.toSlice(ip)); | 933 | .internal => { |
| 934 | zo.symbol(sym_index).flags.is_extern_ptr = true; | 934 | const sym_index = try zo.getOrCreateMetadataForNav(zcu, nav_index); |
| 935 | return .{ .mcv = .{ .lea_symbol = sym_index } }; | 935 | return .{ .mcv = .{ .lea_symbol = sym_index } }; |
| 936 | }, | ||
| 937 | .strong, .weak => { | ||
| 938 | const sym_index = try elf_file.getGlobalSymbol(name.toSlice(ip), lib_name.toSlice(ip)); | ||
| 939 | switch (linkage) { | ||
| 940 | .internal => unreachable, | ||
| 941 | .strong => {}, | ||
| 942 | .weak => zo.symbol(sym_index).flags.weak = true, | ||
| 943 | .link_once => unreachable, | ||
| 944 | } | ||
| 945 | switch (visibility) { | ||
| 946 | .default => zo.symbol(sym_index).flags.is_extern_ptr = true, | ||
| 947 | .hidden, .protected => {}, | ||
| 948 | } | ||
| 949 | return .{ .mcv = .{ .lea_symbol = sym_index } }; | ||
| 950 | }, | ||
| 951 | .link_once => unreachable, | ||
| 936 | } | 952 | } |
| 937 | const sym_index = try zo.getOrCreateMetadataForNav(zcu, nav_index); | ||
| 938 | return .{ .mcv = .{ .lea_symbol = sym_index } }; | ||
| 939 | } else if (lf.cast(.macho)) |macho_file| { | 953 | } else if (lf.cast(.macho)) |macho_file| { |
| 940 | const zo = macho_file.getZigObject().?; | 954 | const zo = macho_file.getZigObject().?; |
| 941 | if (is_extern) { | 955 | switch (linkage) { |
| 942 | const sym_index = try macho_file.getGlobalSymbol(name.toSlice(ip), lib_name.toSlice(ip)); | 956 | .internal => { |
| 943 | zo.symbols.items[sym_index].flags.is_extern_ptr = true; | 957 | const sym_index = try zo.getOrCreateMetadataForNav(macho_file, nav_index); |
| 944 | return .{ .mcv = .{ .lea_symbol = sym_index } }; | 958 | const sym = zo.symbols.items[sym_index]; |
| 959 | return .{ .mcv = .{ .lea_symbol = sym.nlist_idx } }; | ||
| 960 | }, | ||
| 961 | .strong, .weak => { | ||
| 962 | const sym_index = try macho_file.getGlobalSymbol(name.toSlice(ip), lib_name.toSlice(ip)); | ||
| 963 | switch (linkage) { | ||
| 964 | .internal => unreachable, | ||
| 965 | .strong => {}, | ||
| 966 | .weak => zo.symbols.items[sym_index].flags.weak = true, | ||
| 967 | .link_once => unreachable, | ||
| 968 | } | ||
| 969 | switch (visibility) { | ||
| 970 | .default => zo.symbols.items[sym_index].flags.is_extern_ptr = true, | ||
| 971 | .hidden, .protected => {}, | ||
| 972 | } | ||
| 973 | return .{ .mcv = .{ .lea_symbol = sym_index } }; | ||
| 974 | }, | ||
| 975 | .link_once => unreachable, | ||
| 945 | } | 976 | } |
| 946 | const sym_index = try zo.getOrCreateMetadataForNav(macho_file, nav_index); | ||
| 947 | const sym = zo.symbols.items[sym_index]; | ||
| 948 | return .{ .mcv = .{ .lea_symbol = sym.nlist_idx } }; | ||
| 949 | } else if (lf.cast(.coff)) |coff_file| { | 977 | } else if (lf.cast(.coff)) |coff_file| { |
| 950 | if (is_extern) { | 978 | // TODO audit this |
| 951 | // TODO audit this | 979 | switch (linkage) { |
| 952 | const global_index = try coff_file.getGlobalSymbol(name.toSlice(ip), lib_name.toSlice(ip)); | 980 | .internal => { |
| 953 | try coff_file.need_got_table.put(gpa, global_index, {}); // needs GOT | 981 | const atom_index = try coff_file.getOrCreateAtomForNav(nav_index); |
| 954 | return .{ .mcv = .{ .load_got = link.File.Coff.global_symbol_bit | global_index } }; | 982 | const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?; |
| 983 | return .{ .mcv = .{ .load_got = sym_index } }; | ||
| 984 | }, | ||
| 985 | .strong, .weak => { | ||
| 986 | const global_index = try coff_file.getGlobalSymbol(name.toSlice(ip), lib_name.toSlice(ip)); | ||
| 987 | try coff_file.need_got_table.put(gpa, global_index, {}); // needs GOT | ||
| 988 | return .{ .mcv = .{ .load_got = link.File.Coff.global_symbol_bit | global_index } }; | ||
| 989 | }, | ||
| 990 | .link_once => unreachable, | ||
| 955 | } | 991 | } |
| 956 | const atom_index = try coff_file.getOrCreateAtomForNav(nav_index); | ||
| 957 | const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?; | ||
| 958 | return .{ .mcv = .{ .load_got = sym_index } }; | ||
| 959 | } else if (lf.cast(.plan9)) |p9| { | 992 | } else if (lf.cast(.plan9)) |p9| { |
| 960 | const atom_index = try p9.seeNav(pt, nav_index); | 993 | const atom_index = try p9.seeNav(pt, nav_index); |
| 961 | const atom = p9.getAtom(atom_index); | 994 | const atom = p9.getAtom(atom_index); |
src/codegen/c.zig+22-12| ... | @@ -2255,19 +2255,30 @@ pub const DeclGen = struct { | ... | @@ -2255,19 +2255,30 @@ pub const DeclGen = struct { |
| 2255 | fn renderFwdDecl( | 2255 | fn renderFwdDecl( |
| 2256 | dg: *DeclGen, | 2256 | dg: *DeclGen, |
| 2257 | nav_index: InternPool.Nav.Index, | 2257 | nav_index: InternPool.Nav.Index, |
| 2258 | flags: struct { | 2258 | flags: packed struct { |
| 2259 | is_extern: bool, | ||
| 2260 | is_const: bool, | 2259 | is_const: bool, |
| 2261 | is_threadlocal: bool, | 2260 | is_threadlocal: bool, |
| 2262 | is_weak_linkage: bool, | 2261 | linkage: std.builtin.GlobalLinkage, |
| 2262 | visibility: std.builtin.SymbolVisibility, | ||
| 2263 | }, | 2263 | }, |
| 2264 | ) !void { | 2264 | ) !void { |
| 2265 | const zcu = dg.pt.zcu; | 2265 | const zcu = dg.pt.zcu; |
| 2266 | const ip = &zcu.intern_pool; | 2266 | const ip = &zcu.intern_pool; |
| 2267 | const nav = ip.getNav(nav_index); | 2267 | const nav = ip.getNav(nav_index); |
| 2268 | const fwd = dg.fwdDeclWriter(); | 2268 | const fwd = dg.fwdDeclWriter(); |
| 2269 | try fwd.writeAll(if (flags.is_extern) "zig_extern " else "static "); | 2269 | try fwd.writeAll(switch (flags.linkage) { |
| 2270 | if (flags.is_weak_linkage) try fwd.writeAll("zig_weak_linkage "); | 2270 | .internal => "static ", |
| 2271 | .strong, .weak, .link_once => "zig_extern ", | ||
| 2272 | }); | ||
| 2273 | switch (flags.linkage) { | ||
| 2274 | .internal, .strong => {}, | ||
| 2275 | .weak => try fwd.writeAll("zig_weak_linkage "), | ||
| 2276 | .link_once => return dg.fail("TODO: CBE: implement linkonce linkage?", .{}), | ||
| 2277 | } | ||
| 2278 | switch (flags.linkage) { | ||
| 2279 | .internal => {}, | ||
| 2280 | .strong, .weak, .link_once => try fwd.print("zig_visibility({s}) ", .{@tagName(flags.visibility)}), | ||
| 2281 | } | ||
| 2271 | if (flags.is_threadlocal and !dg.mod.single_threaded) try fwd.writeAll("zig_threadlocal "); | 2282 | if (flags.is_threadlocal and !dg.mod.single_threaded) try fwd.writeAll("zig_threadlocal "); |
| 2272 | try dg.renderTypeAndName( | 2283 | try dg.renderTypeAndName( |
| 2273 | fwd, | 2284 | fwd, |
| ... | @@ -2994,10 +3005,10 @@ pub fn genDecl(o: *Object) !void { | ... | @@ -2994,10 +3005,10 @@ pub fn genDecl(o: *Object) !void { |
| 2994 | switch (ip.indexToKey(nav.status.fully_resolved.val)) { | 3005 | switch (ip.indexToKey(nav.status.fully_resolved.val)) { |
| 2995 | .@"extern" => |@"extern"| { | 3006 | .@"extern" => |@"extern"| { |
| 2996 | if (!ip.isFunctionType(nav_ty.toIntern())) return o.dg.renderFwdDecl(o.dg.pass.nav, .{ | 3007 | if (!ip.isFunctionType(nav_ty.toIntern())) return o.dg.renderFwdDecl(o.dg.pass.nav, .{ |
| 2997 | .is_extern = true, | ||
| 2998 | .is_const = @"extern".is_const, | 3008 | .is_const = @"extern".is_const, |
| 2999 | .is_threadlocal = @"extern".is_threadlocal, | 3009 | .is_threadlocal = @"extern".is_threadlocal, |
| 3000 | .is_weak_linkage = @"extern".is_weak_linkage, | 3010 | .linkage = @"extern".linkage, |
| 3011 | .visibility = @"extern".visibility, | ||
| 3001 | }); | 3012 | }); |
| 3002 | 3013 | ||
| 3003 | const fwd = o.dg.fwdDeclWriter(); | 3014 | const fwd = o.dg.fwdDeclWriter(); |
| ... | @@ -3016,13 +3027,12 @@ pub fn genDecl(o: *Object) !void { | ... | @@ -3016,13 +3027,12 @@ pub fn genDecl(o: *Object) !void { |
| 3016 | }, | 3027 | }, |
| 3017 | .variable => |variable| { | 3028 | .variable => |variable| { |
| 3018 | try o.dg.renderFwdDecl(o.dg.pass.nav, .{ | 3029 | try o.dg.renderFwdDecl(o.dg.pass.nav, .{ |
| 3019 | .is_extern = false, | ||
| 3020 | .is_const = false, | 3030 | .is_const = false, |
| 3021 | .is_threadlocal = variable.is_threadlocal, | 3031 | .is_threadlocal = variable.is_threadlocal, |
| 3022 | .is_weak_linkage = variable.is_weak_linkage, | 3032 | .linkage = .internal, |
| 3033 | .visibility = .default, | ||
| 3023 | }); | 3034 | }); |
| 3024 | const w = o.writer(); | 3035 | const w = o.writer(); |
| 3025 | if (variable.is_weak_linkage) try w.writeAll("zig_weak_linkage "); | ||
| 3026 | if (variable.is_threadlocal and !o.dg.mod.single_threaded) try w.writeAll("zig_threadlocal "); | 3036 | if (variable.is_threadlocal and !o.dg.mod.single_threaded) try w.writeAll("zig_threadlocal "); |
| 3027 | if (nav.status.fully_resolved.@"linksection".toSlice(&zcu.intern_pool)) |s| | 3037 | if (nav.status.fully_resolved.@"linksection".toSlice(&zcu.intern_pool)) |s| |
| 3028 | try w.print("zig_linksection({s}) ", .{fmtStringLiteral(s, null)}); | 3038 | try w.print("zig_linksection({s}) ", .{fmtStringLiteral(s, null)}); |
| ... | @@ -3467,7 +3477,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, | ... | @@ -3467,7 +3477,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, |
| 3467 | .error_set_has_value => return f.fail("TODO: C backend: implement error_set_has_value", .{}), | 3477 | .error_set_has_value => return f.fail("TODO: C backend: implement error_set_has_value", .{}), |
| 3468 | .vector_store_elem => return f.fail("TODO: C backend: implement vector_store_elem", .{}), | 3478 | .vector_store_elem => return f.fail("TODO: C backend: implement vector_store_elem", .{}), |
| 3469 | 3479 | ||
| 3470 | .tlv_dllimport_ptr => try airTlvDllimportPtr(f, inst), | 3480 | .runtime_nav_ptr => try airRuntimeNavPtr(f, inst), |
| 3471 | 3481 | ||
| 3472 | .c_va_start => try airCVaStart(f, inst), | 3482 | .c_va_start => try airCVaStart(f, inst), |
| 3473 | .c_va_arg => try airCVaArg(f, inst), | 3483 | .c_va_arg => try airCVaArg(f, inst), |
| ... | @@ -7672,7 +7682,7 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -7672,7 +7682,7 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7672 | return local; | 7682 | return local; |
| 7673 | } | 7683 | } |
| 7674 | 7684 | ||
| 7675 | fn airTlvDllimportPtr(f: *Function, inst: Air.Inst.Index) !CValue { | 7685 | fn airRuntimeNavPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7676 | const ty_nav = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_nav; | 7686 | const ty_nav = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_nav; |
| 7677 | const writer = f.object.writer(); | 7687 | const writer = f.object.writer(); |
| 7678 | const local = try f.allocLocal(inst, .fromInterned(ty_nav.ty)); | 7688 | const local = try f.allocLocal(inst, .fromInterned(ty_nav.ty)); |
src/codegen/llvm.zig+73-50| ... | @@ -2979,36 +2979,49 @@ pub const Object = struct { | ... | @@ -2979,36 +2979,49 @@ pub const Object = struct { |
| 2979 | const zcu = pt.zcu; | 2979 | const zcu = pt.zcu; |
| 2980 | const ip = &zcu.intern_pool; | 2980 | const ip = &zcu.intern_pool; |
| 2981 | const nav = ip.getNav(nav_index); | 2981 | const nav = ip.getNav(nav_index); |
| 2982 | const is_extern, const is_threadlocal, const is_weak_linkage, const is_dll_import = switch (nav.status) { | 2982 | const linkage: std.builtin.GlobalLinkage, const visibility: Builder.Visibility, const is_threadlocal, const is_dll_import = switch (nav.status) { |
| 2983 | .unresolved => unreachable, | 2983 | .unresolved => unreachable, |
| 2984 | .fully_resolved => |r| switch (ip.indexToKey(r.val)) { | 2984 | .fully_resolved => |r| switch (ip.indexToKey(r.val)) { |
| 2985 | .variable => |variable| .{ false, variable.is_threadlocal, variable.is_weak_linkage, false }, | 2985 | .variable => |variable| .{ .internal, .default, variable.is_threadlocal, false }, |
| 2986 | .@"extern" => |@"extern"| .{ true, @"extern".is_threadlocal, @"extern".is_weak_linkage, @"extern".is_dll_import }, | 2986 | .@"extern" => |@"extern"| .{ @"extern".linkage, .fromSymbolVisibility(@"extern".visibility), @"extern".is_threadlocal, @"extern".is_dll_import }, |
| 2987 | else => .{ false, false, false, false }, | 2987 | else => .{ .internal, .default, false, false }, |
| 2988 | }, | 2988 | }, |
| 2989 | // This means it's a source declaration which is not `extern`! | 2989 | // This means it's a source declaration which is not `extern`! |
| 2990 | .type_resolved => |r| .{ false, r.is_threadlocal, false, false }, | 2990 | .type_resolved => |r| .{ .internal, .default, r.is_threadlocal, false }, |
| 2991 | }; | 2991 | }; |
| 2992 | 2992 | ||
| 2993 | const variable_index = try o.builder.addVariable( | 2993 | const variable_index = try o.builder.addVariable( |
| 2994 | try o.builder.strtabString((if (is_extern) nav.name else nav.fqn).toSlice(ip)), | 2994 | try o.builder.strtabString(switch (linkage) { |
| 2995 | .internal => nav.fqn, | ||
| 2996 | .strong, .weak => nav.name, | ||
| 2997 | .link_once => unreachable, | ||
| 2998 | }.toSlice(ip)), | ||
| 2995 | try o.lowerType(Type.fromInterned(nav.typeOf(ip))), | 2999 | try o.lowerType(Type.fromInterned(nav.typeOf(ip))), |
| 2996 | toLlvmGlobalAddressSpace(nav.getAddrspace(), zcu.getTarget()), | 3000 | toLlvmGlobalAddressSpace(nav.getAddrspace(), zcu.getTarget()), |
| 2997 | ); | 3001 | ); |
| 2998 | gop.value_ptr.* = variable_index.ptrConst(&o.builder).global; | 3002 | gop.value_ptr.* = variable_index.ptrConst(&o.builder).global; |
| 2999 | 3003 | ||
| 3000 | // This is needed for declarations created by `@extern`. | 3004 | // This is needed for declarations created by `@extern`. |
| 3001 | if (is_extern) { | 3005 | switch (linkage) { |
| 3002 | variable_index.setLinkage(.external, &o.builder); | 3006 | .internal => { |
| 3003 | variable_index.setUnnamedAddr(.default, &o.builder); | 3007 | variable_index.setLinkage(.internal, &o.builder); |
| 3004 | if (is_threadlocal and !zcu.navFileScope(nav_index).mod.?.single_threaded) | 3008 | variable_index.setUnnamedAddr(.unnamed_addr, &o.builder); |
| 3005 | variable_index.setThreadLocal(.generaldynamic, &o.builder); | 3009 | }, |
| 3006 | if (is_weak_linkage) variable_index.setLinkage(.extern_weak, &o.builder); | 3010 | .strong, .weak => { |
| 3007 | if (is_dll_import) variable_index.setDllStorageClass(.dllimport, &o.builder); | 3011 | variable_index.setLinkage(switch (linkage) { |
| 3008 | } else { | 3012 | .internal => unreachable, |
| 3009 | variable_index.setLinkage(.internal, &o.builder); | 3013 | .strong => .external, |
| 3010 | variable_index.setUnnamedAddr(.unnamed_addr, &o.builder); | 3014 | .weak => .extern_weak, |
| 3011 | } | 3015 | .link_once => unreachable, |
| 3016 | }, &o.builder); | ||
| 3017 | variable_index.setUnnamedAddr(.default, &o.builder); | ||
| 3018 | if (is_threadlocal and !zcu.navFileScope(nav_index).mod.?.single_threaded) | ||
| 3019 | variable_index.setThreadLocal(.generaldynamic, &o.builder); | ||
| 3020 | if (is_dll_import) variable_index.setDllStorageClass(.dllimport, &o.builder); | ||
| 3021 | }, | ||
| 3022 | .link_once => unreachable, | ||
| 3023 | } | ||
| 3024 | variable_index.setVisibility(visibility, &o.builder); | ||
| 3012 | return variable_index; | 3025 | return variable_index; |
| 3013 | } | 3026 | } |
| 3014 | 3027 | ||
| ... | @@ -4530,14 +4543,14 @@ pub const NavGen = struct { | ... | @@ -4530,14 +4543,14 @@ pub const NavGen = struct { |
| 4530 | const nav = ip.getNav(nav_index); | 4543 | const nav = ip.getNav(nav_index); |
| 4531 | const resolved = nav.status.fully_resolved; | 4544 | const resolved = nav.status.fully_resolved; |
| 4532 | 4545 | ||
| 4533 | const is_extern, const lib_name, const is_threadlocal, const is_weak_linkage, const is_dll_import, const is_const, const init_val, const owner_nav = switch (ip.indexToKey(resolved.val)) { | 4546 | const lib_name, const linkage, const visibility: Builder.Visibility, const is_threadlocal, const is_dll_import, const is_const, const init_val, const owner_nav = switch (ip.indexToKey(resolved.val)) { |
| 4534 | .variable => |variable| .{ false, .none, variable.is_threadlocal, variable.is_weak_linkage, false, false, variable.init, variable.owner_nav }, | 4547 | .variable => |variable| .{ .none, .internal, .default, variable.is_threadlocal, false, false, variable.init, variable.owner_nav }, |
| 4535 | .@"extern" => |@"extern"| .{ true, @"extern".lib_name, @"extern".is_threadlocal, @"extern".is_weak_linkage, @"extern".is_dll_import, @"extern".is_const, .none, @"extern".owner_nav }, | 4548 | .@"extern" => |@"extern"| .{ @"extern".lib_name, @"extern".linkage, .fromSymbolVisibility(@"extern".visibility), @"extern".is_threadlocal, @"extern".is_dll_import, @"extern".is_const, .none, @"extern".owner_nav }, |
| 4536 | else => .{ false, .none, false, false, false, true, resolved.val, nav_index }, | 4549 | else => .{ .none, .internal, .default, false, false, true, resolved.val, nav_index }, |
| 4537 | }; | 4550 | }; |
| 4538 | const ty = Type.fromInterned(nav.typeOf(ip)); | 4551 | const ty = Type.fromInterned(nav.typeOf(ip)); |
| 4539 | 4552 | ||
| 4540 | if (is_extern and ip.isFunctionType(ty.toIntern())) { | 4553 | if (linkage != .internal and ip.isFunctionType(ty.toIntern())) { |
| 4541 | _ = try o.resolveLlvmFunction(owner_nav); | 4554 | _ = try o.resolveLlvmFunction(owner_nav); |
| 4542 | } else { | 4555 | } else { |
| 4543 | const variable_index = try o.resolveGlobalNav(nav_index); | 4556 | const variable_index = try o.resolveGlobalNav(nav_index); |
| ... | @@ -4549,6 +4562,7 @@ pub const NavGen = struct { | ... | @@ -4549,6 +4562,7 @@ pub const NavGen = struct { |
| 4549 | .none => .no_init, | 4562 | .none => .no_init, |
| 4550 | else => try o.lowerValue(init_val), | 4563 | else => try o.lowerValue(init_val), |
| 4551 | }, &o.builder); | 4564 | }, &o.builder); |
| 4565 | variable_index.setVisibility(visibility, &o.builder); | ||
| 4552 | 4566 | ||
| 4553 | const file_scope = zcu.navFileScopeIndex(nav_index); | 4567 | const file_scope = zcu.navFileScopeIndex(nav_index); |
| 4554 | const mod = zcu.fileByIndex(file_scope).mod.?; | 4568 | const mod = zcu.fileByIndex(file_scope).mod.?; |
| ... | @@ -4568,7 +4582,7 @@ pub const NavGen = struct { | ... | @@ -4568,7 +4582,7 @@ pub const NavGen = struct { |
| 4568 | line_number, | 4582 | line_number, |
| 4569 | try o.lowerDebugType(ty), | 4583 | try o.lowerDebugType(ty), |
| 4570 | variable_index, | 4584 | variable_index, |
| 4571 | .{ .local = !is_extern }, | 4585 | .{ .local = linkage == .internal }, |
| 4572 | ); | 4586 | ); |
| 4573 | 4587 | ||
| 4574 | const debug_expression = try o.builder.debugExpression(&.{}); | 4588 | const debug_expression = try o.builder.debugExpression(&.{}); |
| ... | @@ -4583,38 +4597,47 @@ pub const NavGen = struct { | ... | @@ -4583,38 +4597,47 @@ pub const NavGen = struct { |
| 4583 | } | 4597 | } |
| 4584 | } | 4598 | } |
| 4585 | 4599 | ||
| 4586 | if (is_extern) { | 4600 | switch (linkage) { |
| 4587 | const global_index = o.nav_map.get(nav_index).?; | 4601 | .internal => {}, |
| 4602 | .strong, .weak => { | ||
| 4603 | const global_index = o.nav_map.get(nav_index).?; | ||
| 4588 | 4604 | ||
| 4589 | const decl_name = decl_name: { | 4605 | const decl_name = decl_name: { |
| 4590 | if (zcu.getTarget().cpu.arch.isWasm() and ty.zigTypeTag(zcu) == .@"fn") { | 4606 | if (zcu.getTarget().cpu.arch.isWasm() and ty.zigTypeTag(zcu) == .@"fn") { |
| 4591 | if (lib_name.toSlice(ip)) |lib_name_slice| { | 4607 | if (lib_name.toSlice(ip)) |lib_name_slice| { |
| 4592 | if (!std.mem.eql(u8, lib_name_slice, "c")) { | 4608 | if (!std.mem.eql(u8, lib_name_slice, "c")) { |
| 4593 | break :decl_name try o.builder.strtabStringFmt("{}|{s}", .{ nav.name.fmt(ip), lib_name_slice }); | 4609 | break :decl_name try o.builder.strtabStringFmt("{}|{s}", .{ nav.name.fmt(ip), lib_name_slice }); |
| 4610 | } | ||
| 4594 | } | 4611 | } |
| 4595 | } | 4612 | } |
| 4596 | } | 4613 | break :decl_name try o.builder.strtabString(nav.name.toSlice(ip)); |
| 4597 | break :decl_name try o.builder.strtabString(nav.name.toSlice(ip)); | 4614 | }; |
| 4598 | }; | ||
| 4599 | 4615 | ||
| 4600 | if (o.builder.getGlobal(decl_name)) |other_global| { | 4616 | if (o.builder.getGlobal(decl_name)) |other_global| { |
| 4601 | if (other_global != global_index) { | 4617 | if (other_global != global_index) { |
| 4602 | // Another global already has this name; just use it in place of this global. | 4618 | // Another global already has this name; just use it in place of this global. |
| 4603 | try global_index.replace(other_global, &o.builder); | 4619 | try global_index.replace(other_global, &o.builder); |
| 4604 | return; | 4620 | return; |
| 4621 | } | ||
| 4605 | } | 4622 | } |
| 4606 | } | ||
| 4607 | 4623 | ||
| 4608 | try global_index.rename(decl_name, &o.builder); | 4624 | try global_index.rename(decl_name, &o.builder); |
| 4609 | global_index.setLinkage(.external, &o.builder); | 4625 | global_index.setUnnamedAddr(.default, &o.builder); |
| 4610 | global_index.setUnnamedAddr(.default, &o.builder); | 4626 | if (is_dll_import) { |
| 4611 | if (is_dll_import) { | 4627 | global_index.setDllStorageClass(.dllimport, &o.builder); |
| 4612 | global_index.setDllStorageClass(.dllimport, &o.builder); | 4628 | } else if (zcu.comp.config.dll_export_fns) { |
| 4613 | } else if (zcu.comp.config.dll_export_fns) { | 4629 | global_index.setDllStorageClass(.default, &o.builder); |
| 4614 | global_index.setDllStorageClass(.default, &o.builder); | 4630 | } |
| 4615 | } | ||
| 4616 | 4631 | ||
| 4617 | if (is_weak_linkage) global_index.setLinkage(.extern_weak, &o.builder); | 4632 | global_index.setLinkage(switch (linkage) { |
| 4633 | .internal => unreachable, | ||
| 4634 | .strong => .external, | ||
| 4635 | .weak => .extern_weak, | ||
| 4636 | .link_once => unreachable, | ||
| 4637 | }, &o.builder); | ||
| 4638 | global_index.setVisibility(visibility, &o.builder); | ||
| 4639 | }, | ||
| 4640 | .link_once => unreachable, | ||
| 4618 | } | 4641 | } |
| 4619 | } | 4642 | } |
| 4620 | }; | 4643 | }; |
| ... | @@ -5023,7 +5046,7 @@ pub const FuncGen = struct { | ... | @@ -5023,7 +5046,7 @@ pub const FuncGen = struct { |
| 5023 | 5046 | ||
| 5024 | .vector_store_elem => try self.airVectorStoreElem(inst), | 5047 | .vector_store_elem => try self.airVectorStoreElem(inst), |
| 5025 | 5048 | ||
| 5026 | .tlv_dllimport_ptr => try self.airTlvDllimportPtr(inst), | 5049 | .runtime_nav_ptr => try self.airRuntimeNavPtr(inst), |
| 5027 | 5050 | ||
| 5028 | .inferred_alloc, .inferred_alloc_comptime => unreachable, | 5051 | .inferred_alloc, .inferred_alloc_comptime => unreachable, |
| 5029 | 5052 | ||
| ... | @@ -8122,7 +8145,7 @@ pub const FuncGen = struct { | ... | @@ -8122,7 +8145,7 @@ pub const FuncGen = struct { |
| 8122 | return .none; | 8145 | return .none; |
| 8123 | } | 8146 | } |
| 8124 | 8147 | ||
| 8125 | fn airTlvDllimportPtr(fg: *FuncGen, inst: Air.Inst.Index) !Builder.Value { | 8148 | fn airRuntimeNavPtr(fg: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 8126 | const o = fg.ng.object; | 8149 | const o = fg.ng.object; |
| 8127 | const ty_nav = fg.air.instructions.items(.data)[@intFromEnum(inst)].ty_nav; | 8150 | const ty_nav = fg.air.instructions.items(.data)[@intFromEnum(inst)].ty_nav; |
| 8128 | const llvm_ptr_const = try o.lowerNavRefValue(ty_nav.nav); | 8151 | const llvm_ptr_const = try o.lowerNavRefValue(ty_nav.nav); |
src/link/Dwarf.zig+52-138| ... | @@ -785,7 +785,6 @@ const Entry = struct { | ... | @@ -785,7 +785,6 @@ const Entry = struct { |
| 785 | } | 785 | } |
| 786 | 786 | ||
| 787 | const Index = enum(u32) { | 787 | const Index = enum(u32) { |
| 788 | //got_proc, | ||
| 789 | _, | 788 | _, |
| 790 | 789 | ||
| 791 | const Optional = enum(u32) { | 790 | const Optional = enum(u32) { |
| ... | @@ -1041,7 +1040,7 @@ const Entry = struct { | ... | @@ -1041,7 +1040,7 @@ const Entry = struct { |
| 1041 | const symbol = zo.symbol(reloc.target_sym); | 1040 | const symbol = zo.symbol(reloc.target_sym); |
| 1042 | try dwarf.resolveReloc( | 1041 | try dwarf.resolveReloc( |
| 1043 | entry_off + reloc.source_off, | 1042 | entry_off + reloc.source_off, |
| 1044 | @bitCast(symbol.address(.{}, elf_file) + @as(i64, @intCast(@intFromEnum(reloc.target_off))) - | 1043 | @bitCast(symbol.address(.{}, elf_file) + @as(i64, @intCast(reloc.target_off)) - |
| 1045 | if (symbol.flags.is_tls) elf_file.dtpAddress() else 0), | 1044 | if (symbol.flags.is_tls) elf_file.dtpAddress() else 0), |
| 1046 | @intFromEnum(dwarf.address_size), | 1045 | @intFromEnum(dwarf.address_size), |
| 1047 | ); | 1046 | ); |
| ... | @@ -1052,7 +1051,7 @@ const Entry = struct { | ... | @@ -1052,7 +1051,7 @@ const Entry = struct { |
| 1052 | const ref = zo.getSymbolRef(reloc.target_sym, macho_file); | 1051 | const ref = zo.getSymbolRef(reloc.target_sym, macho_file); |
| 1053 | try dwarf.resolveReloc( | 1052 | try dwarf.resolveReloc( |
| 1054 | entry_off + reloc.source_off, | 1053 | entry_off + reloc.source_off, |
| 1055 | ref.getSymbol(macho_file).?.getAddress(.{}, macho_file) + @as(i64, @intCast(@intFromEnum(reloc.target_off))), | 1054 | ref.getSymbol(macho_file).?.getAddress(.{}, macho_file) + @as(i64, @intCast(reloc.target_off)), |
| 1056 | @intFromEnum(dwarf.address_size), | 1055 | @intFromEnum(dwarf.address_size), |
| 1057 | ); | 1056 | ); |
| 1058 | } | 1057 | } |
| ... | @@ -1081,27 +1080,12 @@ const CrossSectionReloc = struct { | ... | @@ -1081,27 +1080,12 @@ const CrossSectionReloc = struct { |
| 1081 | const ExternalReloc = struct { | 1080 | const ExternalReloc = struct { |
| 1082 | source_off: u32 = 0, | 1081 | source_off: u32 = 0, |
| 1083 | target_sym: u32, | 1082 | target_sym: u32, |
| 1084 | target_off: enum(u64) { | 1083 | target_off: u64 = 0, |
| 1085 | none = 0, | ||
| 1086 | got = std.math.maxInt(i64) + 1, | ||
| 1087 | _, | ||
| 1088 | |||
| 1089 | pub fn rel(off: u64) @This() { | ||
| 1090 | const res: @This() = @enumFromInt(off); | ||
| 1091 | switch (res) { | ||
| 1092 | .none => {}, | ||
| 1093 | _ => {}, | ||
| 1094 | .got => unreachable, // assertion failure | ||
| 1095 | } | ||
| 1096 | return res; | ||
| 1097 | } | ||
| 1098 | } = .none, | ||
| 1099 | }; | 1084 | }; |
| 1100 | 1085 | ||
| 1101 | pub const Loc = union(enum) { | 1086 | pub const Loc = union(enum) { |
| 1102 | empty, | 1087 | empty, |
| 1103 | addr_reloc: u32, | 1088 | addr_reloc: u32, |
| 1104 | got_reloc: u32, | ||
| 1105 | deref: *const Loc, | 1089 | deref: *const Loc, |
| 1106 | constu: u64, | 1090 | constu: u64, |
| 1107 | consts: i64, | 1091 | consts: i64, |
| ... | @@ -1166,10 +1150,6 @@ pub const Loc = union(enum) { | ... | @@ -1166,10 +1150,6 @@ pub const Loc = union(enum) { |
| 1166 | try addr.write(adapter); | 1150 | try addr.write(adapter); |
| 1167 | try writer.writeByte(DW.OP.deref); | 1151 | try writer.writeByte(DW.OP.deref); |
| 1168 | }, | 1152 | }, |
| 1169 | .got_reloc => |sym_index| { | ||
| 1170 | try writer.writeByte(DW.OP.const4s); | ||
| 1171 | try adapter.gotSym(sym_index); | ||
| 1172 | }, | ||
| 1173 | .constu => |constu| if (std.math.cast(u5, constu)) |lit| { | 1153 | .constu => |constu| if (std.math.cast(u5, constu)) |lit| { |
| 1174 | try writer.writeByte(@as(u8, DW.OP.lit0) + lit); | 1154 | try writer.writeByte(@as(u8, DW.OP.lit0) + lit); |
| 1175 | } else if (std.math.cast(u8, constu)) |const1u| { | 1155 | } else if (std.math.cast(u8, constu)) |const1u| { |
| ... | @@ -1766,9 +1746,6 @@ pub const WipNav = struct { | ... | @@ -1766,9 +1746,6 @@ pub const WipNav = struct { |
| 1766 | fn endian(_: ExprLocCounter) std.builtin.Endian { | 1746 | fn endian(_: ExprLocCounter) std.builtin.Endian { |
| 1767 | return @import("builtin").cpu.arch.endian(); | 1747 | return @import("builtin").cpu.arch.endian(); |
| 1768 | } | 1748 | } |
| 1769 | fn gotSym(counter: *ExprLocCounter, _: u32) error{}!void { | ||
| 1770 | counter.stream.bytes_written += 4; | ||
| 1771 | } | ||
| 1772 | fn addrSym(counter: *ExprLocCounter, _: u32) error{}!void { | 1749 | fn addrSym(counter: *ExprLocCounter, _: u32) error{}!void { |
| 1773 | counter.stream.bytes_written += @intFromEnum(counter.address_size); | 1750 | counter.stream.bytes_written += @intFromEnum(counter.address_size); |
| 1774 | } | 1751 | } |
| ... | @@ -1789,14 +1766,6 @@ pub const WipNav = struct { | ... | @@ -1789,14 +1766,6 @@ pub const WipNav = struct { |
| 1789 | fn endian(ctx: @This()) std.builtin.Endian { | 1766 | fn endian(ctx: @This()) std.builtin.Endian { |
| 1790 | return ctx.wip_nav.dwarf.endian; | 1767 | return ctx.wip_nav.dwarf.endian; |
| 1791 | } | 1768 | } |
| 1792 | fn gotSym(ctx: @This(), sym_index: u32) UpdateError!void { | ||
| 1793 | try ctx.wip_nav.infoExternalReloc(.{ | ||
| 1794 | .source_off = @intCast(ctx.wip_nav.debug_info.items.len), | ||
| 1795 | .target_sym = sym_index, | ||
| 1796 | .target_off = .got, | ||
| 1797 | }); | ||
| 1798 | try ctx.wip_nav.debug_info.appendNTimes(ctx.wip_nav.dwarf.gpa, 0, 4); | ||
| 1799 | } | ||
| 1800 | fn addrSym(ctx: @This(), sym_index: u32) UpdateError!void { | 1769 | fn addrSym(ctx: @This(), sym_index: u32) UpdateError!void { |
| 1801 | try ctx.wip_nav.infoAddrSym(sym_index, 0); | 1770 | try ctx.wip_nav.infoAddrSym(sym_index, 0); |
| 1802 | } | 1771 | } |
| ... | @@ -1812,7 +1781,7 @@ pub const WipNav = struct { | ... | @@ -1812,7 +1781,7 @@ pub const WipNav = struct { |
| 1812 | try wip_nav.infoExternalReloc(.{ | 1781 | try wip_nav.infoExternalReloc(.{ |
| 1813 | .source_off = @intCast(wip_nav.debug_info.items.len), | 1782 | .source_off = @intCast(wip_nav.debug_info.items.len), |
| 1814 | .target_sym = sym_index, | 1783 | .target_sym = sym_index, |
| 1815 | .target_off = .rel(sym_off), | 1784 | .target_off = sym_off, |
| 1816 | }); | 1785 | }); |
| 1817 | try wip_nav.debug_info.appendNTimes(wip_nav.dwarf.gpa, 0, @intFromEnum(wip_nav.dwarf.address_size)); | 1786 | try wip_nav.debug_info.appendNTimes(wip_nav.dwarf.gpa, 0, @intFromEnum(wip_nav.dwarf.address_size)); |
| 1818 | } | 1787 | } |
| ... | @@ -1829,14 +1798,6 @@ pub const WipNav = struct { | ... | @@ -1829,14 +1798,6 @@ pub const WipNav = struct { |
| 1829 | fn endian(ctx: @This()) std.builtin.Endian { | 1798 | fn endian(ctx: @This()) std.builtin.Endian { |
| 1830 | return ctx.wip_nav.dwarf.endian; | 1799 | return ctx.wip_nav.dwarf.endian; |
| 1831 | } | 1800 | } |
| 1832 | fn gotSym(ctx: @This(), sym_index: u32) UpdateError!void { | ||
| 1833 | try ctx.wip_nav.frameExternalReloc(.{ | ||
| 1834 | .source_off = @intCast(ctx.wip_nav.debug_frame.items.len), | ||
| 1835 | .target_sym = sym_index, | ||
| 1836 | .target_off = .got, | ||
| 1837 | }); | ||
| 1838 | try ctx.wip_nav.debug_frame.appendNTimes(ctx.wip_nav.dwarf.gpa, 0, 4); | ||
| 1839 | } | ||
| 1840 | fn addrSym(ctx: @This(), sym_index: u32) UpdateError!void { | 1801 | fn addrSym(ctx: @This(), sym_index: u32) UpdateError!void { |
| 1841 | try ctx.wip_nav.frameAddrSym(sym_index, 0); | 1802 | try ctx.wip_nav.frameAddrSym(sym_index, 0); |
| 1842 | } | 1803 | } |
| ... | @@ -1852,7 +1813,7 @@ pub const WipNav = struct { | ... | @@ -1852,7 +1813,7 @@ pub const WipNav = struct { |
| 1852 | try wip_nav.frameExternalReloc(.{ | 1813 | try wip_nav.frameExternalReloc(.{ |
| 1853 | .source_off = @intCast(wip_nav.debug_frame.items.len), | 1814 | .source_off = @intCast(wip_nav.debug_frame.items.len), |
| 1854 | .target_sym = sym_index, | 1815 | .target_sym = sym_index, |
| 1855 | .target_off = .rel(sym_off), | 1816 | .target_off = sym_off, |
| 1856 | }); | 1817 | }); |
| 1857 | try wip_nav.debug_frame.appendNTimes(wip_nav.dwarf.gpa, 0, @intFromEnum(wip_nav.dwarf.address_size)); | 1818 | try wip_nav.debug_frame.appendNTimes(wip_nav.dwarf.gpa, 0, @intFromEnum(wip_nav.dwarf.address_size)); |
| 1858 | } | 1819 | } |
| ... | @@ -2338,81 +2299,50 @@ fn getUnit(dwarf: *Dwarf, mod: *Module) !Unit.Index { | ... | @@ -2338,81 +2299,50 @@ fn getUnit(dwarf: *Dwarf, mod: *Module) !Unit.Index { |
| 2338 | const mod_gop = try dwarf.mods.getOrPut(dwarf.gpa, mod); | 2299 | const mod_gop = try dwarf.mods.getOrPut(dwarf.gpa, mod); |
| 2339 | const unit: Unit.Index = @enumFromInt(mod_gop.index); | 2300 | const unit: Unit.Index = @enumFromInt(mod_gop.index); |
| 2340 | if (!mod_gop.found_existing) { | 2301 | if (!mod_gop.found_existing) { |
| 2341 | { | 2302 | errdefer _ = dwarf.mods.pop(); |
| 2342 | errdefer _ = dwarf.mods.pop(); | 2303 | mod_gop.value_ptr.* = .{ |
| 2343 | mod_gop.value_ptr.* = .{ | 2304 | .root_dir_path = undefined, |
| 2344 | .root_dir_path = undefined, | 2305 | .dirs = .empty, |
| 2345 | .dirs = .empty, | 2306 | .files = .empty, |
| 2346 | .files = .empty, | 2307 | }; |
| 2347 | }; | 2308 | errdefer mod_gop.value_ptr.dirs.deinit(dwarf.gpa); |
| 2348 | errdefer mod_gop.value_ptr.dirs.deinit(dwarf.gpa); | 2309 | try mod_gop.value_ptr.dirs.putNoClobber(dwarf.gpa, unit, {}); |
| 2349 | try mod_gop.value_ptr.dirs.putNoClobber(dwarf.gpa, unit, {}); | 2310 | assert(try dwarf.debug_aranges.section.addUnit( |
| 2350 | assert(try dwarf.debug_aranges.section.addUnit( | 2311 | DebugAranges.headerBytes(dwarf), |
| 2351 | DebugAranges.headerBytes(dwarf), | 2312 | DebugAranges.trailerBytes(dwarf), |
| 2352 | DebugAranges.trailerBytes(dwarf), | 2313 | dwarf, |
| 2353 | dwarf, | 2314 | ) == unit); |
| 2354 | ) == unit); | 2315 | errdefer dwarf.debug_aranges.section.popUnit(dwarf.gpa); |
| 2355 | errdefer dwarf.debug_aranges.section.popUnit(dwarf.gpa); | 2316 | assert(try dwarf.debug_frame.section.addUnit( |
| 2356 | assert(try dwarf.debug_frame.section.addUnit( | 2317 | DebugFrame.headerBytes(dwarf), |
| 2357 | DebugFrame.headerBytes(dwarf), | 2318 | DebugFrame.trailerBytes(dwarf), |
| 2358 | DebugFrame.trailerBytes(dwarf), | 2319 | dwarf, |
| 2359 | dwarf, | 2320 | ) == unit); |
| 2360 | ) == unit); | 2321 | errdefer dwarf.debug_frame.section.popUnit(dwarf.gpa); |
| 2361 | errdefer dwarf.debug_frame.section.popUnit(dwarf.gpa); | 2322 | assert(try dwarf.debug_info.section.addUnit( |
| 2362 | assert(try dwarf.debug_info.section.addUnit( | 2323 | DebugInfo.headerBytes(dwarf), |
| 2363 | DebugInfo.headerBytes(dwarf), | 2324 | DebugInfo.trailer_bytes, |
| 2364 | DebugInfo.trailer_bytes, | 2325 | dwarf, |
| 2365 | dwarf, | 2326 | ) == unit); |
| 2366 | ) == unit); | 2327 | errdefer dwarf.debug_info.section.popUnit(dwarf.gpa); |
| 2367 | errdefer dwarf.debug_info.section.popUnit(dwarf.gpa); | 2328 | assert(try dwarf.debug_line.section.addUnit( |
| 2368 | assert(try dwarf.debug_line.section.addUnit( | 2329 | DebugLine.headerBytes(dwarf, 5, 25), |
| 2369 | DebugLine.headerBytes(dwarf, 5, 25), | 2330 | DebugLine.trailer_bytes, |
| 2370 | DebugLine.trailer_bytes, | 2331 | dwarf, |
| 2371 | dwarf, | 2332 | ) == unit); |
| 2372 | ) == unit); | 2333 | errdefer dwarf.debug_line.section.popUnit(dwarf.gpa); |
| 2373 | errdefer dwarf.debug_line.section.popUnit(dwarf.gpa); | 2334 | assert(try dwarf.debug_loclists.section.addUnit( |
| 2374 | assert(try dwarf.debug_loclists.section.addUnit( | 2335 | DebugLocLists.headerBytes(dwarf), |
| 2375 | DebugLocLists.headerBytes(dwarf), | 2336 | DebugLocLists.trailer_bytes, |
| 2376 | DebugLocLists.trailer_bytes, | 2337 | dwarf, |
| 2377 | dwarf, | 2338 | ) == unit); |
| 2378 | ) == unit); | 2339 | errdefer dwarf.debug_loclists.section.popUnit(dwarf.gpa); |
| 2379 | errdefer dwarf.debug_loclists.section.popUnit(dwarf.gpa); | 2340 | assert(try dwarf.debug_rnglists.section.addUnit( |
| 2380 | assert(try dwarf.debug_rnglists.section.addUnit( | 2341 | DebugRngLists.headerBytes(dwarf), |
| 2381 | DebugRngLists.headerBytes(dwarf), | 2342 | DebugRngLists.trailer_bytes, |
| 2382 | DebugRngLists.trailer_bytes, | 2343 | dwarf, |
| 2383 | dwarf, | 2344 | ) == unit); |
| 2384 | ) == unit); | 2345 | errdefer dwarf.debug_rnglists.section.popUnit(dwarf.gpa); |
| 2385 | errdefer dwarf.debug_rnglists.section.popUnit(dwarf.gpa); | ||
| 2386 | } | ||
| 2387 | //if (dwarf.bin_file.cast(.elf)) |elf_file| { | ||
| 2388 | // if (unit == .main) assert(try dwarf.addCommonEntry(unit) == .got_proc); | ||
| 2389 | // if (mod.pic and dwarf.debug_info.section.getUnit(.main).getEntry(.got_proc).len == 0) { | ||
| 2390 | // var wip_nav: WipNav = .{ | ||
| 2391 | // .dwarf = dwarf, | ||
| 2392 | // .pt = undefined, | ||
| 2393 | // .unit = .main, | ||
| 2394 | // .entry = .got_proc, | ||
| 2395 | // .any_children = false, | ||
| 2396 | // .func = .none, | ||
| 2397 | // .func_sym_index = undefined, | ||
| 2398 | // .func_high_pc = undefined, | ||
| 2399 | // .blocks = undefined, | ||
| 2400 | // .cfi = undefined, | ||
| 2401 | // .debug_frame = .empty, | ||
| 2402 | // .debug_info = .empty, | ||
| 2403 | // .debug_line = .empty, | ||
| 2404 | // .debug_loclists = .empty, | ||
| 2405 | // .pending_lazy = .empty, | ||
| 2406 | // }; | ||
| 2407 | // defer wip_nav.deinit(); | ||
| 2408 | // try wip_nav.abbrevCode(.proc); | ||
| 2409 | // try wip_nav.infoExprLoc(.{ .deref = &.{ .plus = .{ | ||
| 2410 | // &.empty, | ||
| 2411 | // &.{ .addr_reloc = try elf_file.zigObjectPtr().?.getGlobalSymbol(elf_file, "_GLOBAL_OFFSET_TABLE_", null) }, | ||
| 2412 | // } } }); | ||
| 2413 | // try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.items); | ||
| 2414 | // } | ||
| 2415 | //} | ||
| 2416 | } | 2346 | } |
| 2417 | return unit; | 2347 | return unit; |
| 2418 | } | 2348 | } |
| ... | @@ -2510,16 +2440,7 @@ fn initWipNavInner( | ... | @@ -2510,16 +2440,7 @@ fn initWipNavInner( |
| 2510 | try wip_nav.strp(nav.fqn.toSlice(ip)); | 2440 | try wip_nav.strp(nav.fqn.toSlice(ip)); |
| 2511 | const ty: Type = nav_val.typeOf(zcu); | 2441 | const ty: Type = nav_val.typeOf(zcu); |
| 2512 | const addr: Loc = .{ .addr_reloc = sym_index }; | 2442 | const addr: Loc = .{ .addr_reloc = sym_index }; |
| 2513 | const loc: Loc = loc: { | 2443 | const loc: Loc = if (decl.is_threadlocal) .{ .form_tls_address = &addr } else addr; |
| 2514 | if (dwarf.bin_file.cast(.elf)) |elf_file| if (decl.linkage == .@"extern" and mod.pic) | ||
| 2515 | // TODO: lldb doesn't support call :( | ||
| 2516 | //.{ .call = .{ .args = &.{.{ .got_reloc = sym_index }}, .unit = .main, .entry = .got_proc } } | ||
| 2517 | break :loc .{ .deref = &.{ .plus = .{ | ||
| 2518 | &.{ .addr_reloc = try elf_file.zigObjectPtr().?.getGlobalSymbol(elf_file, "_GLOBAL_OFFSET_TABLE_", null) }, | ||
| 2519 | &.{ .got_reloc = sym_index }, | ||
| 2520 | } } }; | ||
| 2521 | break :loc if (decl.is_threadlocal) .{ .form_tls_address = &addr } else addr; | ||
| 2522 | }; | ||
| 2523 | switch (decl.kind) { | 2444 | switch (decl.kind) { |
| 2524 | .unnamed_test, .@"test", .decltest, .@"comptime", .@"usingnamespace" => unreachable, | 2445 | .unnamed_test, .@"test", .decltest, .@"comptime", .@"usingnamespace" => unreachable, |
| 2525 | .@"const" => { | 2446 | .@"const" => { |
| ... | @@ -2605,7 +2526,7 @@ fn initWipNavInner( | ... | @@ -2605,7 +2526,7 @@ fn initWipNavInner( |
| 2605 | try wip_nav.infoAddrSym(sym_index, 0); | 2526 | try wip_nav.infoAddrSym(sym_index, 0); |
| 2606 | wip_nav.func_high_pc = @intCast(wip_nav.debug_info.items.len); | 2527 | wip_nav.func_high_pc = @intCast(wip_nav.debug_info.items.len); |
| 2607 | try diw.writeInt(u32, 0, dwarf.endian); | 2528 | try diw.writeInt(u32, 0, dwarf.endian); |
| 2608 | const target = file.mod.?.resolved_target.result; | 2529 | const target = mod.resolved_target.result; |
| 2609 | try uleb128(diw, switch (nav.status.fully_resolved.alignment) { | 2530 | try uleb128(diw, switch (nav.status.fully_resolved.alignment) { |
| 2610 | .none => target_info.defaultFunctionAlignment(target), | 2531 | .none => target_info.defaultFunctionAlignment(target), |
| 2611 | else => |a| a.maxStrict(target_info.minFunctionAlignment(target)), | 2532 | else => |a| a.maxStrict(target_info.minFunctionAlignment(target)), |
| ... | @@ -2742,7 +2663,7 @@ pub fn finishWipNavFunc( | ... | @@ -2742,7 +2663,7 @@ pub fn finishWipNavFunc( |
| 2742 | .{ | 2663 | .{ |
| 2743 | .source_off = 1 + @intFromEnum(dwarf.address_size), | 2664 | .source_off = 1 + @intFromEnum(dwarf.address_size), |
| 2744 | .target_sym = wip_nav.func_sym_index, | 2665 | .target_sym = wip_nav.func_sym_index, |
| 2745 | .target_off = .rel(code_size), | 2666 | .target_off = code_size, |
| 2746 | }, | 2667 | }, |
| 2747 | }); | 2668 | }); |
| 2748 | try dwarf.debug_rnglists.section.replaceEntry( | 2669 | try dwarf.debug_rnglists.section.replaceEntry( |
| ... | @@ -4981,7 +4902,6 @@ const AbbrevCode = enum { | ... | @@ -4981,7 +4902,6 @@ const AbbrevCode = enum { |
| 4981 | comptime_value_field_comptime_state, | 4902 | comptime_value_field_comptime_state, |
| 4982 | comptime_value_elem_runtime_bits, | 4903 | comptime_value_elem_runtime_bits, |
| 4983 | comptime_value_elem_comptime_state, | 4904 | comptime_value_elem_comptime_state, |
| 4984 | //proc, | ||
| 4985 | 4905 | ||
| 4986 | const decl_bytes = uleb128Bytes(@intFromEnum(AbbrevCode.decl_instance_func_generic)); | 4906 | const decl_bytes = uleb128Bytes(@intFromEnum(AbbrevCode.decl_instance_func_generic)); |
| 4987 | comptime { | 4907 | comptime { |
| ... | @@ -5851,12 +5771,6 @@ const AbbrevCode = enum { | ... | @@ -5851,12 +5771,6 @@ const AbbrevCode = enum { |
| 5851 | .{ .ZIG_comptime_value, .ref_addr }, | 5771 | .{ .ZIG_comptime_value, .ref_addr }, |
| 5852 | }, | 5772 | }, |
| 5853 | }, | 5773 | }, |
| 5854 | //.proc = .{ | ||
| 5855 | // .tag = .dwarf_procedure, | ||
| 5856 | // .attrs = &.{ | ||
| 5857 | // .{ .location, .exprloc }, | ||
| 5858 | // }, | ||
| 5859 | //}, | ||
| 5860 | .null = undefined, | 5774 | .null = undefined, |
| 5861 | }); | 5775 | }); |
| 5862 | }; | 5776 | }; |
src/link/Elf.zig+25-17| ... | @@ -959,6 +959,12 @@ fn flushModuleInner(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id) !void { | ... | @@ -959,6 +959,12 @@ fn flushModuleInner(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id) !void { |
| 959 | self.rela_plt.clearRetainingCapacity(); | 959 | self.rela_plt.clearRetainingCapacity(); |
| 960 | 960 | ||
| 961 | if (self.zigObjectPtr()) |zo| { | 961 | if (self.zigObjectPtr()) |zo| { |
| 962 | var undefs: std.AutoArrayHashMap(SymbolResolver.Index, std.ArrayList(Ref)) = .init(gpa); | ||
| 963 | defer { | ||
| 964 | for (undefs.values()) |*refs| refs.deinit(); | ||
| 965 | undefs.deinit(); | ||
| 966 | } | ||
| 967 | |||
| 962 | var has_reloc_errors = false; | 968 | var has_reloc_errors = false; |
| 963 | for (zo.atoms_indexes.items) |atom_index| { | 969 | for (zo.atoms_indexes.items) |atom_index| { |
| 964 | const atom_ptr = zo.atom(atom_index) orelse continue; | 970 | const atom_ptr = zo.atom(atom_index) orelse continue; |
| ... | @@ -969,7 +975,10 @@ fn flushModuleInner(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id) !void { | ... | @@ -969,7 +975,10 @@ fn flushModuleInner(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id) !void { |
| 969 | const code = try zo.codeAlloc(self, atom_index); | 975 | const code = try zo.codeAlloc(self, atom_index); |
| 970 | defer gpa.free(code); | 976 | defer gpa.free(code); |
| 971 | const file_offset = atom_ptr.offset(self); | 977 | const file_offset = atom_ptr.offset(self); |
| 972 | atom_ptr.resolveRelocsAlloc(self, code) catch |err| switch (err) { | 978 | (if (shdr.sh_flags & elf.SHF_ALLOC == 0) |
| 979 | atom_ptr.resolveRelocsNonAlloc(self, code, &undefs) | ||
| 980 | else | ||
| 981 | atom_ptr.resolveRelocsAlloc(self, code)) catch |err| switch (err) { | ||
| 973 | error.RelocFailure, error.RelaxFailure => has_reloc_errors = true, | 982 | error.RelocFailure, error.RelaxFailure => has_reloc_errors = true, |
| 974 | error.UnsupportedCpuArch => { | 983 | error.UnsupportedCpuArch => { |
| 975 | try self.reportUnsupportedCpuArch(); | 984 | try self.reportUnsupportedCpuArch(); |
| ... | @@ -980,6 +989,8 @@ fn flushModuleInner(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id) !void { | ... | @@ -980,6 +989,8 @@ fn flushModuleInner(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id) !void { |
| 980 | try self.pwriteAll(code, file_offset); | 989 | try self.pwriteAll(code, file_offset); |
| 981 | } | 990 | } |
| 982 | 991 | ||
| 992 | try self.reportUndefinedSymbols(&undefs); | ||
| 993 | |||
| 983 | if (has_reloc_errors) return error.LinkFailure; | 994 | if (has_reloc_errors) return error.LinkFailure; |
| 984 | } | 995 | } |
| 985 | 996 | ||
| ... | @@ -1392,11 +1403,9 @@ fn scanRelocs(self: *Elf) !void { | ... | @@ -1392,11 +1403,9 @@ fn scanRelocs(self: *Elf) !void { |
| 1392 | const gpa = self.base.comp.gpa; | 1403 | const gpa = self.base.comp.gpa; |
| 1393 | const shared_objects = self.shared_objects.values(); | 1404 | const shared_objects = self.shared_objects.values(); |
| 1394 | 1405 | ||
| 1395 | var undefs = std.AutoArrayHashMap(SymbolResolver.Index, std.ArrayList(Ref)).init(gpa); | 1406 | var undefs: std.AutoArrayHashMap(SymbolResolver.Index, std.ArrayList(Ref)) = .init(gpa); |
| 1396 | defer { | 1407 | defer { |
| 1397 | for (undefs.values()) |*refs| { | 1408 | for (undefs.values()) |*refs| refs.deinit(); |
| 1398 | refs.deinit(); | ||
| 1399 | } | ||
| 1400 | undefs.deinit(); | 1409 | undefs.deinit(); |
| 1401 | } | 1410 | } |
| 1402 | 1411 | ||
| ... | @@ -2702,15 +2711,16 @@ fn initSyntheticSections(self: *Elf) !void { | ... | @@ -2702,15 +2711,16 @@ fn initSyntheticSections(self: *Elf) !void { |
| 2702 | }); | 2711 | }); |
| 2703 | } | 2712 | } |
| 2704 | 2713 | ||
| 2705 | const needs_interp = blk: { | 2714 | const is_exe_or_dyn_lib = switch (comp.config.output_mode) { |
| 2706 | // On Ubuntu with musl-gcc, we get a weird combo of options looking like this: | 2715 | .Exe => true, |
| 2707 | // -dynamic-linker=<path> -static | 2716 | .Lib => comp.config.link_mode == .dynamic, |
| 2708 | // In this case, if we do generate .interp section and segment, we will get | 2717 | .Obj => false, |
| 2709 | // a segfault in the dynamic linker trying to load a binary that is static | ||
| 2710 | // and doesn't contain .dynamic section. | ||
| 2711 | if (self.base.isStatic() and !comp.config.pie) break :blk false; | ||
| 2712 | break :blk target.dynamic_linker.get() != null; | ||
| 2713 | }; | 2718 | }; |
| 2719 | const have_dynamic_linker = comp.config.link_mode == .dynamic and is_exe_or_dyn_lib and !target.dynamic_linker.eql(.none); | ||
| 2720 | |||
| 2721 | const needs_interp = have_dynamic_linker and | ||
| 2722 | (comp.config.link_libc or comp.root_mod.resolved_target.is_explicit_dynamic_linker); | ||
| 2723 | |||
| 2714 | if (needs_interp and self.section_indexes.interp == null) { | 2724 | if (needs_interp and self.section_indexes.interp == null) { |
| 2715 | self.section_indexes.interp = try self.addSection(.{ | 2725 | self.section_indexes.interp = try self.addSection(.{ |
| 2716 | .name = try self.insertShString(".interp"), | 2726 | .name = try self.insertShString(".interp"), |
| ... | @@ -3707,11 +3717,9 @@ fn allocateSpecialPhdrs(self: *Elf) void { | ... | @@ -3707,11 +3717,9 @@ fn allocateSpecialPhdrs(self: *Elf) void { |
| 3707 | fn writeAtoms(self: *Elf) !void { | 3717 | fn writeAtoms(self: *Elf) !void { |
| 3708 | const gpa = self.base.comp.gpa; | 3718 | const gpa = self.base.comp.gpa; |
| 3709 | 3719 | ||
| 3710 | var undefs = std.AutoArrayHashMap(SymbolResolver.Index, std.ArrayList(Ref)).init(gpa); | 3720 | var undefs: std.AutoArrayHashMap(SymbolResolver.Index, std.ArrayList(Ref)) = .init(gpa); |
| 3711 | defer { | 3721 | defer { |
| 3712 | for (undefs.values()) |*refs| { | 3722 | for (undefs.values()) |*refs| refs.deinit(); |
| 3713 | refs.deinit(); | ||
| 3714 | } | ||
| 3715 | undefs.deinit(); | 3723 | undefs.deinit(); |
| 3716 | } | 3724 | } |
| 3717 | 3725 |
src/link/Elf/Atom.zig+3-3| ... | @@ -497,14 +497,14 @@ fn dynAbsRelocAction(symbol: *const Symbol, elf_file: *Elf) RelocAction { | ... | @@ -497,14 +497,14 @@ fn dynAbsRelocAction(symbol: *const Symbol, elf_file: *Elf) RelocAction { |
| 497 | } | 497 | } |
| 498 | 498 | ||
| 499 | fn outputType(elf_file: *Elf) u2 { | 499 | fn outputType(elf_file: *Elf) u2 { |
| 500 | const comp = elf_file.base.comp; | ||
| 501 | assert(!elf_file.base.isRelocatable()); | 500 | assert(!elf_file.base.isRelocatable()); |
| 502 | return switch (elf_file.base.comp.config.output_mode) { | 501 | const config = &elf_file.base.comp.config; |
| 502 | return switch (config.output_mode) { | ||
| 503 | .Obj => unreachable, | 503 | .Obj => unreachable, |
| 504 | .Lib => 0, | 504 | .Lib => 0, |
| 505 | .Exe => switch (elf_file.getTarget().os.tag) { | 505 | .Exe => switch (elf_file.getTarget().os.tag) { |
| 506 | .haiku => 0, | 506 | .haiku => 0, |
| 507 | else => if (comp.config.pie) 1 else 2, | 507 | else => if (config.pie) 1 else 2, |
| 508 | }, | 508 | }, |
| 509 | }; | 509 | }; |
| 510 | } | 510 | } |
src/link/Elf/ZigObject.zig+5-7| ... | @@ -463,11 +463,8 @@ pub fn flush(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !void { | ... | @@ -463,11 +463,8 @@ pub fn flush(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !void { |
| 463 | for (entry.external_relocs.items) |reloc| { | 463 | for (entry.external_relocs.items) |reloc| { |
| 464 | const target_sym = self.symbol(reloc.target_sym); | 464 | const target_sym = self.symbol(reloc.target_sym); |
| 465 | const r_offset = entry_off + reloc.source_off; | 465 | const r_offset = entry_off + reloc.source_off; |
| 466 | const r_addend: i64 = switch (reloc.target_off) { | 466 | const r_addend: i64 = @intCast(reloc.target_off); |
| 467 | .none, .got => 0, | 467 | const r_type = relocation.dwarf.externalRelocType(target_sym.*, sect_index, dwarf.address_size, cpu_arch); |
| 468 | else => |off| @intCast(@intFromEnum(off)), | ||
| 469 | }; | ||
| 470 | const r_type = relocation.dwarf.externalRelocType(target_sym.*, reloc.target_off == .got, sect_index, dwarf.address_size, cpu_arch); | ||
| 471 | atom_ptr.addRelocAssumeCapacity(.{ | 468 | atom_ptr.addRelocAssumeCapacity(.{ |
| 472 | .r_offset = r_offset, | 469 | .r_offset = r_offset, |
| 473 | .r_addend = r_addend, | 470 | .r_addend = r_addend, |
| ... | @@ -660,6 +657,7 @@ pub fn scanRelocs(self: *ZigObject, elf_file: *Elf, undefs: anytype) !void { | ... | @@ -660,6 +657,7 @@ pub fn scanRelocs(self: *ZigObject, elf_file: *Elf, undefs: anytype) !void { |
| 660 | const atom_ptr = self.atom(atom_index) orelse continue; | 657 | const atom_ptr = self.atom(atom_index) orelse continue; |
| 661 | if (!atom_ptr.alive) continue; | 658 | if (!atom_ptr.alive) continue; |
| 662 | const shdr = atom_ptr.inputShdr(elf_file); | 659 | const shdr = atom_ptr.inputShdr(elf_file); |
| 660 | if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue; | ||
| 663 | if (shdr.sh_type == elf.SHT_NOBITS) continue; | 661 | if (shdr.sh_type == elf.SHT_NOBITS) continue; |
| 664 | if (atom_ptr.scanRelocsRequiresCode(elf_file)) { | 662 | if (atom_ptr.scanRelocsRequiresCode(elf_file)) { |
| 665 | // TODO ideally we don't have to fetch the code here. | 663 | // TODO ideally we don't have to fetch the code here. |
| ... | @@ -950,7 +948,7 @@ pub fn getNavVAddr( | ... | @@ -950,7 +948,7 @@ pub fn getNavVAddr( |
| 950 | .dwarf => |wip_nav| try wip_nav.infoExternalReloc(.{ | 948 | .dwarf => |wip_nav| try wip_nav.infoExternalReloc(.{ |
| 951 | .source_off = @intCast(reloc_info.offset), | 949 | .source_off = @intCast(reloc_info.offset), |
| 952 | .target_sym = this_sym_index, | 950 | .target_sym = this_sym_index, |
| 953 | .target_off = .rel(reloc_info.addend), | 951 | .target_off = reloc_info.addend, |
| 954 | }), | 952 | }), |
| 955 | .plan9 => unreachable, | 953 | .plan9 => unreachable, |
| 956 | .none => unreachable, | 954 | .none => unreachable, |
| ... | @@ -983,7 +981,7 @@ pub fn getUavVAddr( | ... | @@ -983,7 +981,7 @@ pub fn getUavVAddr( |
| 983 | .dwarf => |wip_nav| try wip_nav.infoExternalReloc(.{ | 981 | .dwarf => |wip_nav| try wip_nav.infoExternalReloc(.{ |
| 984 | .source_off = @intCast(reloc_info.offset), | 982 | .source_off = @intCast(reloc_info.offset), |
| 985 | .target_sym = sym_index, | 983 | .target_sym = sym_index, |
| 986 | .target_off = .rel(reloc_info.addend), | 984 | .target_off = reloc_info.addend, |
| 987 | }), | 985 | }), |
| 988 | .plan9 => unreachable, | 986 | .plan9 => unreachable, |
| 989 | .none => unreachable, | 987 | .none => unreachable, |
src/link/Elf/relocation.zig+1-2| ... | @@ -108,13 +108,12 @@ pub const dwarf = struct { | ... | @@ -108,13 +108,12 @@ pub const dwarf = struct { |
| 108 | 108 | ||
| 109 | pub fn externalRelocType( | 109 | pub fn externalRelocType( |
| 110 | target: Symbol, | 110 | target: Symbol, |
| 111 | is_got: bool, | ||
| 112 | source_section: Dwarf.Section.Index, | 111 | source_section: Dwarf.Section.Index, |
| 113 | address_size: Dwarf.AddressSize, | 112 | address_size: Dwarf.AddressSize, |
| 114 | cpu_arch: std.Target.Cpu.Arch, | 113 | cpu_arch: std.Target.Cpu.Arch, |
| 115 | ) u32 { | 114 | ) u32 { |
| 116 | return switch (cpu_arch) { | 115 | return switch (cpu_arch) { |
| 117 | .x86_64 => @intFromEnum(@as(elf.R_X86_64, if (is_got) .GOT32 else switch (source_section) { | 116 | .x86_64 => @intFromEnum(@as(elf.R_X86_64, switch (source_section) { |
| 118 | else => switch (address_size) { | 117 | else => switch (address_size) { |
| 119 | .@"32" => if (target.flags.is_tls) .DTPOFF32 else .@"32", | 118 | .@"32" => if (target.flags.is_tls) .DTPOFF32 else .@"32", |
| 120 | .@"64" => if (target.flags.is_tls) .DTPOFF64 else .@"64", | 119 | .@"64" => if (target.flags.is_tls) .DTPOFF64 else .@"64", |
src/link/MachO/ZigObject.zig+2-2| ... | @@ -648,7 +648,7 @@ pub fn getNavVAddr( | ... | @@ -648,7 +648,7 @@ pub fn getNavVAddr( |
| 648 | .dwarf => |wip_nav| try wip_nav.infoExternalReloc(.{ | 648 | .dwarf => |wip_nav| try wip_nav.infoExternalReloc(.{ |
| 649 | .source_off = @intCast(reloc_info.offset), | 649 | .source_off = @intCast(reloc_info.offset), |
| 650 | .target_sym = sym_index, | 650 | .target_sym = sym_index, |
| 651 | .target_off = .rel(reloc_info.addend), | 651 | .target_off = reloc_info.addend, |
| 652 | }), | 652 | }), |
| 653 | .plan9 => unreachable, | 653 | .plan9 => unreachable, |
| 654 | .none => unreachable, | 654 | .none => unreachable, |
| ... | @@ -688,7 +688,7 @@ pub fn getUavVAddr( | ... | @@ -688,7 +688,7 @@ pub fn getUavVAddr( |
| 688 | .dwarf => |wip_nav| try wip_nav.infoExternalReloc(.{ | 688 | .dwarf => |wip_nav| try wip_nav.infoExternalReloc(.{ |
| 689 | .source_off = @intCast(reloc_info.offset), | 689 | .source_off = @intCast(reloc_info.offset), |
| 690 | .target_sym = sym_index, | 690 | .target_sym = sym_index, |
| 691 | .target_off = .rel(reloc_info.addend), | 691 | .target_off = reloc_info.addend, |
| 692 | }), | 692 | }), |
| 693 | .plan9 => unreachable, | 693 | .plan9 => unreachable, |
| 694 | .none => unreachable, | 694 | .none => unreachable, |
src/link/Wasm.zig+1-1| ... | @@ -2376,7 +2376,7 @@ pub const FunctionImportId = enum(u32) { | ... | @@ -2376,7 +2376,7 @@ pub const FunctionImportId = enum(u32) { |
| 2376 | const zcu = wasm.base.comp.zcu.?; | 2376 | const zcu = wasm.base.comp.zcu.?; |
| 2377 | const ip = &zcu.intern_pool; | 2377 | const ip = &zcu.intern_pool; |
| 2378 | const ext = ip.getNav(i.ptr(wasm).*).getResolvedExtern(ip).?; | 2378 | const ext = ip.getNav(i.ptr(wasm).*).getResolvedExtern(ip).?; |
| 2379 | return !ext.is_weak_linkage and ext.lib_name != .none; | 2379 | return ext.linkage != .weak and ext.lib_name != .none; |
| 2380 | }, | 2380 | }, |
| 2381 | }; | 2381 | }; |
| 2382 | } | 2382 | } |
src/print_air.zig deleted-1038| ... | @@ -1,1038 +0,0 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const Allocator = std.mem.Allocator; | ||
| 3 | const fmtIntSizeBin = std.fmt.fmtIntSizeBin; | ||
| 4 | |||
| 5 | const Zcu = @import("Zcu.zig"); | ||
| 6 | const Value = @import("Value.zig"); | ||
| 7 | const Type = @import("Type.zig"); | ||
| 8 | const Air = @import("Air.zig"); | ||
| 9 | const InternPool = @import("InternPool.zig"); | ||
| 10 | |||
| 11 | pub fn write(stream: anytype, pt: Zcu.PerThread, air: Air, liveness: ?Air.Liveness) void { | ||
| 12 | const instruction_bytes = air.instructions.len * | ||
| 13 | // Here we don't use @sizeOf(Air.Inst.Data) because it would include | ||
| 14 | // the debug safety tag but we want to measure release size. | ||
| 15 | (@sizeOf(Air.Inst.Tag) + 8); | ||
| 16 | const extra_bytes = air.extra.items.len * @sizeOf(u32); | ||
| 17 | const tomb_bytes = if (liveness) |l| l.tomb_bits.len * @sizeOf(usize) else 0; | ||
| 18 | const liveness_extra_bytes = if (liveness) |l| l.extra.len * @sizeOf(u32) else 0; | ||
| 19 | const liveness_special_bytes = if (liveness) |l| l.special.count() * 8 else 0; | ||
| 20 | const total_bytes = @sizeOf(Air) + instruction_bytes + extra_bytes + | ||
| 21 | @sizeOf(Air.Liveness) + liveness_extra_bytes + | ||
| 22 | liveness_special_bytes + tomb_bytes; | ||
| 23 | |||
| 24 | // zig fmt: off | ||
| 25 | stream.print( | ||
| 26 | \\# Total AIR+Liveness bytes: {} | ||
| 27 | \\# AIR Instructions: {d} ({}) | ||
| 28 | \\# AIR Extra Data: {d} ({}) | ||
| 29 | \\# Liveness tomb_bits: {} | ||
| 30 | \\# Liveness Extra Data: {d} ({}) | ||
| 31 | \\# Liveness special table: {d} ({}) | ||
| 32 | \\ | ||
| 33 | , .{ | ||
| 34 | fmtIntSizeBin(total_bytes), | ||
| 35 | air.instructions.len, fmtIntSizeBin(instruction_bytes), | ||
| 36 | air.extra.items.len, fmtIntSizeBin(extra_bytes), | ||
| 37 | fmtIntSizeBin(tomb_bytes), | ||
| 38 | if (liveness) |l| l.extra.len else 0, fmtIntSizeBin(liveness_extra_bytes), | ||
| 39 | if (liveness) |l| l.special.count() else 0, fmtIntSizeBin(liveness_special_bytes), | ||
| 40 | }) catch return; | ||
| 41 | // zig fmt: on | ||
| 42 | |||
| 43 | var writer: Writer = .{ | ||
| 44 | .pt = pt, | ||
| 45 | .gpa = pt.zcu.gpa, | ||
| 46 | .air = air, | ||
| 47 | .liveness = liveness, | ||
| 48 | .indent = 2, | ||
| 49 | .skip_body = false, | ||
| 50 | }; | ||
| 51 | writer.writeBody(stream, air.getMainBody()) catch return; | ||
| 52 | } | ||
| 53 | |||
| 54 | pub fn writeInst( | ||
| 55 | stream: anytype, | ||
| 56 | inst: Air.Inst.Index, | ||
| 57 | pt: Zcu.PerThread, | ||
| 58 | air: Air, | ||
| 59 | liveness: ?Air.Liveness, | ||
| 60 | ) void { | ||
| 61 | var writer: Writer = .{ | ||
| 62 | .pt = pt, | ||
| 63 | .gpa = pt.zcu.gpa, | ||
| 64 | .air = air, | ||
| 65 | .liveness = liveness, | ||
| 66 | .indent = 2, | ||
| 67 | .skip_body = true, | ||
| 68 | }; | ||
| 69 | writer.writeInst(stream, inst) catch return; | ||
| 70 | } | ||
| 71 | |||
| 72 | pub fn dump(pt: Zcu.PerThread, air: Air, liveness: ?Air.Liveness) void { | ||
| 73 | write(std.io.getStdErr().writer(), pt, air, liveness); | ||
| 74 | } | ||
| 75 | |||
| 76 | pub fn dumpInst(inst: Air.Inst.Index, pt: Zcu.PerThread, air: Air, liveness: ?Air.Liveness) void { | ||
| 77 | writeInst(std.io.getStdErr().writer(), inst, pt, air, liveness); | ||
| 78 | } | ||
| 79 | |||
| 80 | const Writer = struct { | ||
| 81 | pt: Zcu.PerThread, | ||
| 82 | gpa: Allocator, | ||
| 83 | air: Air, | ||
| 84 | liveness: ?Air.Liveness, | ||
| 85 | indent: usize, | ||
| 86 | skip_body: bool, | ||
| 87 | |||
| 88 | fn writeBody(w: *Writer, s: anytype, body: []const Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 89 | for (body) |inst| { | ||
| 90 | try w.writeInst(s, inst); | ||
| 91 | try s.writeByte('\n'); | ||
| 92 | } | ||
| 93 | } | ||
| 94 | |||
| 95 | fn writeInst(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 96 | const tag = w.air.instructions.items(.tag)[@intFromEnum(inst)]; | ||
| 97 | try s.writeByteNTimes(' ', w.indent); | ||
| 98 | try s.print("{}{c}= {s}(", .{ | ||
| 99 | inst, | ||
| 100 | @as(u8, if (if (w.liveness) |liveness| liveness.isUnused(inst) else false) '!' else ' '), | ||
| 101 | @tagName(tag), | ||
| 102 | }); | ||
| 103 | switch (tag) { | ||
| 104 | .add, | ||
| 105 | .add_optimized, | ||
| 106 | .add_safe, | ||
| 107 | .add_wrap, | ||
| 108 | .add_sat, | ||
| 109 | .sub, | ||
| 110 | .sub_optimized, | ||
| 111 | .sub_safe, | ||
| 112 | .sub_wrap, | ||
| 113 | .sub_sat, | ||
| 114 | .mul, | ||
| 115 | .mul_optimized, | ||
| 116 | .mul_safe, | ||
| 117 | .mul_wrap, | ||
| 118 | .mul_sat, | ||
| 119 | .div_float, | ||
| 120 | .div_trunc, | ||
| 121 | .div_floor, | ||
| 122 | .div_exact, | ||
| 123 | .rem, | ||
| 124 | .mod, | ||
| 125 | .bit_and, | ||
| 126 | .bit_or, | ||
| 127 | .xor, | ||
| 128 | .cmp_lt, | ||
| 129 | .cmp_lte, | ||
| 130 | .cmp_eq, | ||
| 131 | .cmp_gte, | ||
| 132 | .cmp_gt, | ||
| 133 | .cmp_neq, | ||
| 134 | .bool_and, | ||
| 135 | .bool_or, | ||
| 136 | .store, | ||
| 137 | .store_safe, | ||
| 138 | .array_elem_val, | ||
| 139 | .slice_elem_val, | ||
| 140 | .ptr_elem_val, | ||
| 141 | .shl, | ||
| 142 | .shl_exact, | ||
| 143 | .shl_sat, | ||
| 144 | .shr, | ||
| 145 | .shr_exact, | ||
| 146 | .set_union_tag, | ||
| 147 | .min, | ||
| 148 | .max, | ||
| 149 | .div_float_optimized, | ||
| 150 | .div_trunc_optimized, | ||
| 151 | .div_floor_optimized, | ||
| 152 | .div_exact_optimized, | ||
| 153 | .rem_optimized, | ||
| 154 | .mod_optimized, | ||
| 155 | .cmp_lt_optimized, | ||
| 156 | .cmp_lte_optimized, | ||
| 157 | .cmp_eq_optimized, | ||
| 158 | .cmp_gte_optimized, | ||
| 159 | .cmp_gt_optimized, | ||
| 160 | .cmp_neq_optimized, | ||
| 161 | .memcpy, | ||
| 162 | .memmove, | ||
| 163 | .memset, | ||
| 164 | .memset_safe, | ||
| 165 | => try w.writeBinOp(s, inst), | ||
| 166 | |||
| 167 | .is_null, | ||
| 168 | .is_non_null, | ||
| 169 | .is_null_ptr, | ||
| 170 | .is_non_null_ptr, | ||
| 171 | .is_err, | ||
| 172 | .is_non_err, | ||
| 173 | .is_err_ptr, | ||
| 174 | .is_non_err_ptr, | ||
| 175 | .ret, | ||
| 176 | .ret_safe, | ||
| 177 | .ret_load, | ||
| 178 | .is_named_enum_value, | ||
| 179 | .tag_name, | ||
| 180 | .error_name, | ||
| 181 | .sqrt, | ||
| 182 | .sin, | ||
| 183 | .cos, | ||
| 184 | .tan, | ||
| 185 | .exp, | ||
| 186 | .exp2, | ||
| 187 | .log, | ||
| 188 | .log2, | ||
| 189 | .log10, | ||
| 190 | .floor, | ||
| 191 | .ceil, | ||
| 192 | .round, | ||
| 193 | .trunc_float, | ||
| 194 | .neg, | ||
| 195 | .neg_optimized, | ||
| 196 | .cmp_lt_errors_len, | ||
| 197 | .set_err_return_trace, | ||
| 198 | .c_va_end, | ||
| 199 | => try w.writeUnOp(s, inst), | ||
| 200 | |||
| 201 | .trap, | ||
| 202 | .breakpoint, | ||
| 203 | .dbg_empty_stmt, | ||
| 204 | .unreach, | ||
| 205 | .ret_addr, | ||
| 206 | .frame_addr, | ||
| 207 | .save_err_return_trace_index, | ||
| 208 | => try w.writeNoOp(s, inst), | ||
| 209 | |||
| 210 | .alloc, | ||
| 211 | .ret_ptr, | ||
| 212 | .err_return_trace, | ||
| 213 | .c_va_start, | ||
| 214 | => try w.writeTy(s, inst), | ||
| 215 | |||
| 216 | .arg => try w.writeArg(s, inst), | ||
| 217 | |||
| 218 | .not, | ||
| 219 | .bitcast, | ||
| 220 | .load, | ||
| 221 | .fptrunc, | ||
| 222 | .fpext, | ||
| 223 | .intcast, | ||
| 224 | .intcast_safe, | ||
| 225 | .trunc, | ||
| 226 | .optional_payload, | ||
| 227 | .optional_payload_ptr, | ||
| 228 | .optional_payload_ptr_set, | ||
| 229 | .errunion_payload_ptr_set, | ||
| 230 | .wrap_optional, | ||
| 231 | .unwrap_errunion_payload, | ||
| 232 | .unwrap_errunion_err, | ||
| 233 | .unwrap_errunion_payload_ptr, | ||
| 234 | .unwrap_errunion_err_ptr, | ||
| 235 | .wrap_errunion_payload, | ||
| 236 | .wrap_errunion_err, | ||
| 237 | .slice_ptr, | ||
| 238 | .slice_len, | ||
| 239 | .ptr_slice_len_ptr, | ||
| 240 | .ptr_slice_ptr_ptr, | ||
| 241 | .struct_field_ptr_index_0, | ||
| 242 | .struct_field_ptr_index_1, | ||
| 243 | .struct_field_ptr_index_2, | ||
| 244 | .struct_field_ptr_index_3, | ||
| 245 | .array_to_slice, | ||
| 246 | .float_from_int, | ||
| 247 | .splat, | ||
| 248 | .int_from_float, | ||
| 249 | .int_from_float_optimized, | ||
| 250 | .get_union_tag, | ||
| 251 | .clz, | ||
| 252 | .ctz, | ||
| 253 | .popcount, | ||
| 254 | .byte_swap, | ||
| 255 | .bit_reverse, | ||
| 256 | .abs, | ||
| 257 | .error_set_has_value, | ||
| 258 | .addrspace_cast, | ||
| 259 | .c_va_arg, | ||
| 260 | .c_va_copy, | ||
| 261 | => try w.writeTyOp(s, inst), | ||
| 262 | |||
| 263 | .block, .dbg_inline_block => try w.writeBlock(s, tag, inst), | ||
| 264 | |||
| 265 | .loop => try w.writeLoop(s, inst), | ||
| 266 | |||
| 267 | .slice, | ||
| 268 | .slice_elem_ptr, | ||
| 269 | .ptr_elem_ptr, | ||
| 270 | .ptr_add, | ||
| 271 | .ptr_sub, | ||
| 272 | .add_with_overflow, | ||
| 273 | .sub_with_overflow, | ||
| 274 | .mul_with_overflow, | ||
| 275 | .shl_with_overflow, | ||
| 276 | => try w.writeTyPlBin(s, inst), | ||
| 277 | |||
| 278 | .call, | ||
| 279 | .call_always_tail, | ||
| 280 | .call_never_tail, | ||
| 281 | .call_never_inline, | ||
| 282 | => try w.writeCall(s, inst), | ||
| 283 | |||
| 284 | .dbg_var_ptr, | ||
| 285 | .dbg_var_val, | ||
| 286 | .dbg_arg_inline, | ||
| 287 | => try w.writeDbgVar(s, inst), | ||
| 288 | |||
| 289 | .struct_field_ptr => try w.writeStructField(s, inst), | ||
| 290 | .struct_field_val => try w.writeStructField(s, inst), | ||
| 291 | .inferred_alloc => @panic("TODO"), | ||
| 292 | .inferred_alloc_comptime => @panic("TODO"), | ||
| 293 | .assembly => try w.writeAssembly(s, inst), | ||
| 294 | .dbg_stmt => try w.writeDbgStmt(s, inst), | ||
| 295 | |||
| 296 | .aggregate_init => try w.writeAggregateInit(s, inst), | ||
| 297 | .union_init => try w.writeUnionInit(s, inst), | ||
| 298 | .br => try w.writeBr(s, inst), | ||
| 299 | .switch_dispatch => try w.writeBr(s, inst), | ||
| 300 | .repeat => try w.writeRepeat(s, inst), | ||
| 301 | .cond_br => try w.writeCondBr(s, inst), | ||
| 302 | .@"try", .try_cold => try w.writeTry(s, inst), | ||
| 303 | .try_ptr, .try_ptr_cold => try w.writeTryPtr(s, inst), | ||
| 304 | .loop_switch_br, .switch_br => try w.writeSwitchBr(s, inst), | ||
| 305 | .cmpxchg_weak, .cmpxchg_strong => try w.writeCmpxchg(s, inst), | ||
| 306 | .atomic_load => try w.writeAtomicLoad(s, inst), | ||
| 307 | .prefetch => try w.writePrefetch(s, inst), | ||
| 308 | .atomic_store_unordered => try w.writeAtomicStore(s, inst, .unordered), | ||
| 309 | .atomic_store_monotonic => try w.writeAtomicStore(s, inst, .monotonic), | ||
| 310 | .atomic_store_release => try w.writeAtomicStore(s, inst, .release), | ||
| 311 | .atomic_store_seq_cst => try w.writeAtomicStore(s, inst, .seq_cst), | ||
| 312 | .atomic_rmw => try w.writeAtomicRmw(s, inst), | ||
| 313 | .field_parent_ptr => try w.writeFieldParentPtr(s, inst), | ||
| 314 | .wasm_memory_size => try w.writeWasmMemorySize(s, inst), | ||
| 315 | .wasm_memory_grow => try w.writeWasmMemoryGrow(s, inst), | ||
| 316 | .mul_add => try w.writeMulAdd(s, inst), | ||
| 317 | .select => try w.writeSelect(s, inst), | ||
| 318 | .shuffle_one => try w.writeShuffleOne(s, inst), | ||
| 319 | .shuffle_two => try w.writeShuffleTwo(s, inst), | ||
| 320 | .reduce, .reduce_optimized => try w.writeReduce(s, inst), | ||
| 321 | .cmp_vector, .cmp_vector_optimized => try w.writeCmpVector(s, inst), | ||
| 322 | .vector_store_elem => try w.writeVectorStoreElem(s, inst), | ||
| 323 | .tlv_dllimport_ptr => try w.writeTlvDllimportPtr(s, inst), | ||
| 324 | |||
| 325 | .work_item_id, | ||
| 326 | .work_group_size, | ||
| 327 | .work_group_id, | ||
| 328 | => try w.writeWorkDimension(s, inst), | ||
| 329 | } | ||
| 330 | try s.writeByte(')'); | ||
| 331 | } | ||
| 332 | |||
| 333 | fn writeBinOp(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 334 | const bin_op = w.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; | ||
| 335 | try w.writeOperand(s, inst, 0, bin_op.lhs); | ||
| 336 | try s.writeAll(", "); | ||
| 337 | try w.writeOperand(s, inst, 1, bin_op.rhs); | ||
| 338 | } | ||
| 339 | |||
| 340 | fn writeUnOp(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 341 | const un_op = w.air.instructions.items(.data)[@intFromEnum(inst)].un_op; | ||
| 342 | try w.writeOperand(s, inst, 0, un_op); | ||
| 343 | } | ||
| 344 | |||
| 345 | fn writeNoOp(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 346 | _ = w; | ||
| 347 | _ = inst; | ||
| 348 | // no-op, no argument to write | ||
| 349 | } | ||
| 350 | |||
| 351 | fn writeType(w: *Writer, s: anytype, ty: Type) !void { | ||
| 352 | return ty.print(s, w.pt); | ||
| 353 | } | ||
| 354 | |||
| 355 | fn writeTy(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 356 | const ty = w.air.instructions.items(.data)[@intFromEnum(inst)].ty; | ||
| 357 | try w.writeType(s, ty); | ||
| 358 | } | ||
| 359 | |||
| 360 | fn writeArg(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 361 | const arg = w.air.instructions.items(.data)[@intFromEnum(inst)].arg; | ||
| 362 | try w.writeType(s, arg.ty.toType()); | ||
| 363 | switch (arg.name) { | ||
| 364 | .none => {}, | ||
| 365 | _ => try s.print(", \"{}\"", .{std.zig.fmtEscapes(arg.name.toSlice(w.air))}), | ||
| 366 | } | ||
| 367 | } | ||
| 368 | |||
| 369 | fn writeTyOp(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 370 | const ty_op = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; | ||
| 371 | try w.writeType(s, ty_op.ty.toType()); | ||
| 372 | try s.writeAll(", "); | ||
| 373 | try w.writeOperand(s, inst, 0, ty_op.operand); | ||
| 374 | } | ||
| 375 | |||
| 376 | fn writeBlock(w: *Writer, s: anytype, tag: Air.Inst.Tag, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 377 | const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; | ||
| 378 | try w.writeType(s, ty_pl.ty.toType()); | ||
| 379 | const body: []const Air.Inst.Index = @ptrCast(switch (tag) { | ||
| 380 | inline .block, .dbg_inline_block => |comptime_tag| body: { | ||
| 381 | const extra = w.air.extraData(switch (comptime_tag) { | ||
| 382 | .block => Air.Block, | ||
| 383 | .dbg_inline_block => Air.DbgInlineBlock, | ||
| 384 | else => unreachable, | ||
| 385 | }, ty_pl.payload); | ||
| 386 | switch (comptime_tag) { | ||
| 387 | .block => {}, | ||
| 388 | .dbg_inline_block => { | ||
| 389 | try s.writeAll(", "); | ||
| 390 | try w.writeInstRef(s, Air.internedToRef(extra.data.func), false); | ||
| 391 | }, | ||
| 392 | else => unreachable, | ||
| 393 | } | ||
| 394 | break :body w.air.extra.items[extra.end..][0..extra.data.body_len]; | ||
| 395 | }, | ||
| 396 | else => unreachable, | ||
| 397 | }); | ||
| 398 | if (w.skip_body) return s.writeAll(", ..."); | ||
| 399 | const liveness_block: Air.Liveness.BlockSlices = if (w.liveness) |liveness| | ||
| 400 | liveness.getBlock(inst) | ||
| 401 | else | ||
| 402 | .{ .deaths = &.{} }; | ||
| 403 | |||
| 404 | try s.writeAll(", {\n"); | ||
| 405 | const old_indent = w.indent; | ||
| 406 | w.indent += 2; | ||
| 407 | try w.writeBody(s, body); | ||
| 408 | w.indent = old_indent; | ||
| 409 | try s.writeByteNTimes(' ', w.indent); | ||
| 410 | try s.writeAll("}"); | ||
| 411 | |||
| 412 | for (liveness_block.deaths) |operand| { | ||
| 413 | try s.print(" {}!", .{operand}); | ||
| 414 | } | ||
| 415 | } | ||
| 416 | |||
| 417 | fn writeLoop(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 418 | const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; | ||
| 419 | const extra = w.air.extraData(Air.Block, ty_pl.payload); | ||
| 420 | const body: []const Air.Inst.Index = @ptrCast(w.air.extra.items[extra.end..][0..extra.data.body_len]); | ||
| 421 | |||
| 422 | try w.writeType(s, ty_pl.ty.toType()); | ||
| 423 | if (w.skip_body) return s.writeAll(", ..."); | ||
| 424 | try s.writeAll(", {\n"); | ||
| 425 | const old_indent = w.indent; | ||
| 426 | w.indent += 2; | ||
| 427 | try w.writeBody(s, body); | ||
| 428 | w.indent = old_indent; | ||
| 429 | try s.writeByteNTimes(' ', w.indent); | ||
| 430 | try s.writeAll("}"); | ||
| 431 | } | ||
| 432 | |||
| 433 | fn writeAggregateInit(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 434 | const zcu = w.pt.zcu; | ||
| 435 | const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; | ||
| 436 | const vector_ty = ty_pl.ty.toType(); | ||
| 437 | const len = @as(usize, @intCast(vector_ty.arrayLen(zcu))); | ||
| 438 | const elements = @as([]const Air.Inst.Ref, @ptrCast(w.air.extra.items[ty_pl.payload..][0..len])); | ||
| 439 | |||
| 440 | try w.writeType(s, vector_ty); | ||
| 441 | try s.writeAll(", ["); | ||
| 442 | for (elements, 0..) |elem, i| { | ||
| 443 | if (i != 0) try s.writeAll(", "); | ||
| 444 | try w.writeOperand(s, inst, i, elem); | ||
| 445 | } | ||
| 446 | try s.writeAll("]"); | ||
| 447 | } | ||
| 448 | |||
| 449 | fn writeUnionInit(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 450 | const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; | ||
| 451 | const extra = w.air.extraData(Air.UnionInit, ty_pl.payload).data; | ||
| 452 | |||
| 453 | try s.print("{d}, ", .{extra.field_index}); | ||
| 454 | try w.writeOperand(s, inst, 0, extra.init); | ||
| 455 | } | ||
| 456 | |||
| 457 | fn writeStructField(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 458 | const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; | ||
| 459 | const extra = w.air.extraData(Air.StructField, ty_pl.payload).data; | ||
| 460 | |||
| 461 | try w.writeOperand(s, inst, 0, extra.struct_operand); | ||
| 462 | try s.print(", {d}", .{extra.field_index}); | ||
| 463 | } | ||
| 464 | |||
| 465 | fn writeTyPlBin(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 466 | const data = w.air.instructions.items(.data); | ||
| 467 | const ty_pl = data[@intFromEnum(inst)].ty_pl; | ||
| 468 | const extra = w.air.extraData(Air.Bin, ty_pl.payload).data; | ||
| 469 | |||
| 470 | const inst_ty = data[@intFromEnum(inst)].ty_pl.ty.toType(); | ||
| 471 | try w.writeType(s, inst_ty); | ||
| 472 | try s.writeAll(", "); | ||
| 473 | try w.writeOperand(s, inst, 0, extra.lhs); | ||
| 474 | try s.writeAll(", "); | ||
| 475 | try w.writeOperand(s, inst, 1, extra.rhs); | ||
| 476 | } | ||
| 477 | |||
| 478 | fn writeCmpxchg(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 479 | const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; | ||
| 480 | const extra = w.air.extraData(Air.Cmpxchg, ty_pl.payload).data; | ||
| 481 | |||
| 482 | try w.writeOperand(s, inst, 0, extra.ptr); | ||
| 483 | try s.writeAll(", "); | ||
| 484 | try w.writeOperand(s, inst, 1, extra.expected_value); | ||
| 485 | try s.writeAll(", "); | ||
| 486 | try w.writeOperand(s, inst, 2, extra.new_value); | ||
| 487 | try s.print(", {s}, {s}", .{ | ||
| 488 | @tagName(extra.successOrder()), @tagName(extra.failureOrder()), | ||
| 489 | }); | ||
| 490 | } | ||
| 491 | |||
| 492 | fn writeMulAdd(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 493 | const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; | ||
| 494 | const extra = w.air.extraData(Air.Bin, pl_op.payload).data; | ||
| 495 | |||
| 496 | try w.writeOperand(s, inst, 0, extra.lhs); | ||
| 497 | try s.writeAll(", "); | ||
| 498 | try w.writeOperand(s, inst, 1, extra.rhs); | ||
| 499 | try s.writeAll(", "); | ||
| 500 | try w.writeOperand(s, inst, 2, pl_op.operand); | ||
| 501 | } | ||
| 502 | |||
| 503 | fn writeShuffleOne(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 504 | const unwrapped = w.air.unwrapShuffleOne(w.pt.zcu, inst); | ||
| 505 | try w.writeType(s, unwrapped.result_ty); | ||
| 506 | try s.writeAll(", "); | ||
| 507 | try w.writeOperand(s, inst, 0, unwrapped.operand); | ||
| 508 | try s.writeAll(", ["); | ||
| 509 | for (unwrapped.mask, 0..) |mask_elem, mask_idx| { | ||
| 510 | if (mask_idx > 0) try s.writeAll(", "); | ||
| 511 | switch (mask_elem.unwrap()) { | ||
| 512 | .elem => |idx| try s.print("elem {d}", .{idx}), | ||
| 513 | .value => |val| try s.print("val {}", .{Value.fromInterned(val).fmtValue(w.pt)}), | ||
| 514 | } | ||
| 515 | } | ||
| 516 | try s.writeByte(']'); | ||
| 517 | } | ||
| 518 | |||
| 519 | fn writeShuffleTwo(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 520 | const unwrapped = w.air.unwrapShuffleTwo(w.pt.zcu, inst); | ||
| 521 | try w.writeType(s, unwrapped.result_ty); | ||
| 522 | try s.writeAll(", "); | ||
| 523 | try w.writeOperand(s, inst, 0, unwrapped.operand_a); | ||
| 524 | try s.writeAll(", "); | ||
| 525 | try w.writeOperand(s, inst, 1, unwrapped.operand_b); | ||
| 526 | try s.writeAll(", ["); | ||
| 527 | for (unwrapped.mask, 0..) |mask_elem, mask_idx| { | ||
| 528 | if (mask_idx > 0) try s.writeAll(", "); | ||
| 529 | switch (mask_elem.unwrap()) { | ||
| 530 | .a_elem => |idx| try s.print("a_elem {d}", .{idx}), | ||
| 531 | .b_elem => |idx| try s.print("b_elem {d}", .{idx}), | ||
| 532 | .undef => try s.writeAll("undef"), | ||
| 533 | } | ||
| 534 | } | ||
| 535 | try s.writeByte(']'); | ||
| 536 | } | ||
| 537 | |||
| 538 | fn writeSelect(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 539 | const zcu = w.pt.zcu; | ||
| 540 | const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; | ||
| 541 | const extra = w.air.extraData(Air.Bin, pl_op.payload).data; | ||
| 542 | |||
| 543 | const elem_ty = w.typeOfIndex(inst).childType(zcu); | ||
| 544 | try w.writeType(s, elem_ty); | ||
| 545 | try s.writeAll(", "); | ||
| 546 | try w.writeOperand(s, inst, 0, pl_op.operand); | ||
| 547 | try s.writeAll(", "); | ||
| 548 | try w.writeOperand(s, inst, 1, extra.lhs); | ||
| 549 | try s.writeAll(", "); | ||
| 550 | try w.writeOperand(s, inst, 2, extra.rhs); | ||
| 551 | } | ||
| 552 | |||
| 553 | fn writeReduce(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 554 | const reduce = w.air.instructions.items(.data)[@intFromEnum(inst)].reduce; | ||
| 555 | |||
| 556 | try w.writeOperand(s, inst, 0, reduce.operand); | ||
| 557 | try s.print(", {s}", .{@tagName(reduce.operation)}); | ||
| 558 | } | ||
| 559 | |||
| 560 | fn writeCmpVector(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 561 | const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; | ||
| 562 | const extra = w.air.extraData(Air.VectorCmp, ty_pl.payload).data; | ||
| 563 | |||
| 564 | try s.print("{s}, ", .{@tagName(extra.compareOperator())}); | ||
| 565 | try w.writeOperand(s, inst, 0, extra.lhs); | ||
| 566 | try s.writeAll(", "); | ||
| 567 | try w.writeOperand(s, inst, 1, extra.rhs); | ||
| 568 | } | ||
| 569 | |||
| 570 | fn writeVectorStoreElem(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 571 | const data = w.air.instructions.items(.data)[@intFromEnum(inst)].vector_store_elem; | ||
| 572 | const extra = w.air.extraData(Air.VectorCmp, data.payload).data; | ||
| 573 | |||
| 574 | try w.writeOperand(s, inst, 0, data.vector_ptr); | ||
| 575 | try s.writeAll(", "); | ||
| 576 | try w.writeOperand(s, inst, 1, extra.lhs); | ||
| 577 | try s.writeAll(", "); | ||
| 578 | try w.writeOperand(s, inst, 2, extra.rhs); | ||
| 579 | } | ||
| 580 | |||
| 581 | fn writeTlvDllimportPtr(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 582 | const ip = &w.pt.zcu.intern_pool; | ||
| 583 | const ty_nav = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_nav; | ||
| 584 | try w.writeType(s, .fromInterned(ty_nav.ty)); | ||
| 585 | try s.print(", '{}'", .{ip.getNav(ty_nav.nav).fqn.fmt(ip)}); | ||
| 586 | } | ||
| 587 | |||
| 588 | fn writeAtomicLoad(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 589 | const atomic_load = w.air.instructions.items(.data)[@intFromEnum(inst)].atomic_load; | ||
| 590 | |||
| 591 | try w.writeOperand(s, inst, 0, atomic_load.ptr); | ||
| 592 | try s.print(", {s}", .{@tagName(atomic_load.order)}); | ||
| 593 | } | ||
| 594 | |||
| 595 | fn writePrefetch(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 596 | const prefetch = w.air.instructions.items(.data)[@intFromEnum(inst)].prefetch; | ||
| 597 | |||
| 598 | try w.writeOperand(s, inst, 0, prefetch.ptr); | ||
| 599 | try s.print(", {s}, {d}, {s}", .{ | ||
| 600 | @tagName(prefetch.rw), prefetch.locality, @tagName(prefetch.cache), | ||
| 601 | }); | ||
| 602 | } | ||
| 603 | |||
| 604 | fn writeAtomicStore( | ||
| 605 | w: *Writer, | ||
| 606 | s: anytype, | ||
| 607 | inst: Air.Inst.Index, | ||
| 608 | order: std.builtin.AtomicOrder, | ||
| 609 | ) @TypeOf(s).Error!void { | ||
| 610 | const bin_op = w.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; | ||
| 611 | try w.writeOperand(s, inst, 0, bin_op.lhs); | ||
| 612 | try s.writeAll(", "); | ||
| 613 | try w.writeOperand(s, inst, 1, bin_op.rhs); | ||
| 614 | try s.print(", {s}", .{@tagName(order)}); | ||
| 615 | } | ||
| 616 | |||
| 617 | fn writeAtomicRmw(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 618 | const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; | ||
| 619 | const extra = w.air.extraData(Air.AtomicRmw, pl_op.payload).data; | ||
| 620 | |||
| 621 | try w.writeOperand(s, inst, 0, pl_op.operand); | ||
| 622 | try s.writeAll(", "); | ||
| 623 | try w.writeOperand(s, inst, 1, extra.operand); | ||
| 624 | try s.print(", {s}, {s}", .{ @tagName(extra.op()), @tagName(extra.ordering()) }); | ||
| 625 | } | ||
| 626 | |||
| 627 | fn writeFieldParentPtr(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 628 | const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; | ||
| 629 | const extra = w.air.extraData(Air.FieldParentPtr, ty_pl.payload).data; | ||
| 630 | |||
| 631 | try w.writeOperand(s, inst, 0, extra.field_ptr); | ||
| 632 | try s.print(", {d}", .{extra.field_index}); | ||
| 633 | } | ||
| 634 | |||
| 635 | fn writeAssembly(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 636 | const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; | ||
| 637 | const extra = w.air.extraData(Air.Asm, ty_pl.payload); | ||
| 638 | const is_volatile = @as(u1, @truncate(extra.data.flags >> 31)) != 0; | ||
| 639 | const clobbers_len = @as(u31, @truncate(extra.data.flags)); | ||
| 640 | var extra_i: usize = extra.end; | ||
| 641 | var op_index: usize = 0; | ||
| 642 | |||
| 643 | const ret_ty = w.typeOfIndex(inst); | ||
| 644 | try w.writeType(s, ret_ty); | ||
| 645 | |||
| 646 | if (is_volatile) { | ||
| 647 | try s.writeAll(", volatile"); | ||
| 648 | } | ||
| 649 | |||
| 650 | const outputs = @as([]const Air.Inst.Ref, @ptrCast(w.air.extra.items[extra_i..][0..extra.data.outputs_len])); | ||
| 651 | extra_i += outputs.len; | ||
| 652 | const inputs = @as([]const Air.Inst.Ref, @ptrCast(w.air.extra.items[extra_i..][0..extra.data.inputs_len])); | ||
| 653 | extra_i += inputs.len; | ||
| 654 | |||
| 655 | for (outputs) |output| { | ||
| 656 | const extra_bytes = std.mem.sliceAsBytes(w.air.extra.items[extra_i..]); | ||
| 657 | const constraint = std.mem.sliceTo(extra_bytes, 0); | ||
| 658 | const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0); | ||
| 659 | |||
| 660 | // This equation accounts for the fact that even if we have exactly 4 bytes | ||
| 661 | // for the strings and their null terminators, we still use the next u32 | ||
| 662 | // for the null terminator. | ||
| 663 | extra_i += (constraint.len + name.len + (2 + 3)) / 4; | ||
| 664 | |||
| 665 | if (output == .none) { | ||
| 666 | try s.print(", [{s}] -> {s}", .{ name, constraint }); | ||
| 667 | } else { | ||
| 668 | try s.print(", [{s}] out {s} = (", .{ name, constraint }); | ||
| 669 | try w.writeOperand(s, inst, op_index, output); | ||
| 670 | op_index += 1; | ||
| 671 | try s.writeByte(')'); | ||
| 672 | } | ||
| 673 | } | ||
| 674 | |||
| 675 | for (inputs) |input| { | ||
| 676 | const extra_bytes = std.mem.sliceAsBytes(w.air.extra.items[extra_i..]); | ||
| 677 | const constraint = std.mem.sliceTo(extra_bytes, 0); | ||
| 678 | const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0); | ||
| 679 | // This equation accounts for the fact that even if we have exactly 4 bytes | ||
| 680 | // for the strings and their null terminators, we still use the next u32 | ||
| 681 | // for the null terminator. | ||
| 682 | extra_i += (constraint.len + name.len + 1) / 4 + 1; | ||
| 683 | |||
| 684 | try s.print(", [{s}] in {s} = (", .{ name, constraint }); | ||
| 685 | try w.writeOperand(s, inst, op_index, input); | ||
| 686 | op_index += 1; | ||
| 687 | try s.writeByte(')'); | ||
| 688 | } | ||
| 689 | |||
| 690 | { | ||
| 691 | var clobber_i: u32 = 0; | ||
| 692 | while (clobber_i < clobbers_len) : (clobber_i += 1) { | ||
| 693 | const extra_bytes = std.mem.sliceAsBytes(w.air.extra.items[extra_i..]); | ||
| 694 | const clobber = std.mem.sliceTo(extra_bytes, 0); | ||
| 695 | // This equation accounts for the fact that even if we have exactly 4 bytes | ||
| 696 | // for the string, we still use the next u32 for the null terminator. | ||
| 697 | extra_i += clobber.len / 4 + 1; | ||
| 698 | |||
| 699 | try s.writeAll(", ~{"); | ||
| 700 | try s.writeAll(clobber); | ||
| 701 | try s.writeAll("}"); | ||
| 702 | } | ||
| 703 | } | ||
| 704 | const asm_source = std.mem.sliceAsBytes(w.air.extra.items[extra_i..])[0..extra.data.source_len]; | ||
| 705 | try s.print(", \"{}\"", .{std.zig.fmtEscapes(asm_source)}); | ||
| 706 | } | ||
| 707 | |||
| 708 | fn writeDbgStmt(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 709 | const dbg_stmt = w.air.instructions.items(.data)[@intFromEnum(inst)].dbg_stmt; | ||
| 710 | try s.print("{d}:{d}", .{ dbg_stmt.line + 1, dbg_stmt.column + 1 }); | ||
| 711 | } | ||
| 712 | |||
| 713 | fn writeDbgVar(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 714 | const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; | ||
| 715 | try w.writeOperand(s, inst, 0, pl_op.operand); | ||
| 716 | const name: Air.NullTerminatedString = @enumFromInt(pl_op.payload); | ||
| 717 | try s.print(", \"{}\"", .{std.zig.fmtEscapes(name.toSlice(w.air))}); | ||
| 718 | } | ||
| 719 | |||
| 720 | fn writeCall(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 721 | const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; | ||
| 722 | const extra = w.air.extraData(Air.Call, pl_op.payload); | ||
| 723 | const args = @as([]const Air.Inst.Ref, @ptrCast(w.air.extra.items[extra.end..][0..extra.data.args_len])); | ||
| 724 | try w.writeOperand(s, inst, 0, pl_op.operand); | ||
| 725 | try s.writeAll(", ["); | ||
| 726 | for (args, 0..) |arg, i| { | ||
| 727 | if (i != 0) try s.writeAll(", "); | ||
| 728 | try w.writeOperand(s, inst, 1 + i, arg); | ||
| 729 | } | ||
| 730 | try s.writeAll("]"); | ||
| 731 | } | ||
| 732 | |||
| 733 | fn writeBr(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 734 | const br = w.air.instructions.items(.data)[@intFromEnum(inst)].br; | ||
| 735 | try w.writeInstIndex(s, br.block_inst, false); | ||
| 736 | try s.writeAll(", "); | ||
| 737 | try w.writeOperand(s, inst, 0, br.operand); | ||
| 738 | } | ||
| 739 | |||
| 740 | fn writeRepeat(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 741 | const repeat = w.air.instructions.items(.data)[@intFromEnum(inst)].repeat; | ||
| 742 | try w.writeInstIndex(s, repeat.loop_inst, false); | ||
| 743 | } | ||
| 744 | |||
| 745 | fn writeTry(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 746 | const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; | ||
| 747 | const extra = w.air.extraData(Air.Try, pl_op.payload); | ||
| 748 | const body: []const Air.Inst.Index = @ptrCast(w.air.extra.items[extra.end..][0..extra.data.body_len]); | ||
| 749 | const liveness_condbr: Air.Liveness.CondBrSlices = if (w.liveness) |liveness| | ||
| 750 | liveness.getCondBr(inst) | ||
| 751 | else | ||
| 752 | .{ .then_deaths = &.{}, .else_deaths = &.{} }; | ||
| 753 | |||
| 754 | try w.writeOperand(s, inst, 0, pl_op.operand); | ||
| 755 | if (w.skip_body) return s.writeAll(", ..."); | ||
| 756 | try s.writeAll(", {\n"); | ||
| 757 | const old_indent = w.indent; | ||
| 758 | w.indent += 2; | ||
| 759 | |||
| 760 | if (liveness_condbr.else_deaths.len != 0) { | ||
| 761 | try s.writeByteNTimes(' ', w.indent); | ||
| 762 | for (liveness_condbr.else_deaths, 0..) |operand, i| { | ||
| 763 | if (i != 0) try s.writeAll(" "); | ||
| 764 | try s.print("{}!", .{operand}); | ||
| 765 | } | ||
| 766 | try s.writeAll("\n"); | ||
| 767 | } | ||
| 768 | try w.writeBody(s, body); | ||
| 769 | |||
| 770 | w.indent = old_indent; | ||
| 771 | try s.writeByteNTimes(' ', w.indent); | ||
| 772 | try s.writeAll("}"); | ||
| 773 | |||
| 774 | for (liveness_condbr.then_deaths) |operand| { | ||
| 775 | try s.print(" {}!", .{operand}); | ||
| 776 | } | ||
| 777 | } | ||
| 778 | |||
| 779 | fn writeTryPtr(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 780 | const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; | ||
| 781 | const extra = w.air.extraData(Air.TryPtr, ty_pl.payload); | ||
| 782 | const body: []const Air.Inst.Index = @ptrCast(w.air.extra.items[extra.end..][0..extra.data.body_len]); | ||
| 783 | const liveness_condbr: Air.Liveness.CondBrSlices = if (w.liveness) |liveness| | ||
| 784 | liveness.getCondBr(inst) | ||
| 785 | else | ||
| 786 | .{ .then_deaths = &.{}, .else_deaths = &.{} }; | ||
| 787 | |||
| 788 | try w.writeOperand(s, inst, 0, extra.data.ptr); | ||
| 789 | |||
| 790 | try s.writeAll(", "); | ||
| 791 | try w.writeType(s, ty_pl.ty.toType()); | ||
| 792 | if (w.skip_body) return s.writeAll(", ..."); | ||
| 793 | try s.writeAll(", {\n"); | ||
| 794 | const old_indent = w.indent; | ||
| 795 | w.indent += 2; | ||
| 796 | |||
| 797 | if (liveness_condbr.else_deaths.len != 0) { | ||
| 798 | try s.writeByteNTimes(' ', w.indent); | ||
| 799 | for (liveness_condbr.else_deaths, 0..) |operand, i| { | ||
| 800 | if (i != 0) try s.writeAll(" "); | ||
| 801 | try s.print("{}!", .{operand}); | ||
| 802 | } | ||
| 803 | try s.writeAll("\n"); | ||
| 804 | } | ||
| 805 | try w.writeBody(s, body); | ||
| 806 | |||
| 807 | w.indent = old_indent; | ||
| 808 | try s.writeByteNTimes(' ', w.indent); | ||
| 809 | try s.writeAll("}"); | ||
| 810 | |||
| 811 | for (liveness_condbr.then_deaths) |operand| { | ||
| 812 | try s.print(" {}!", .{operand}); | ||
| 813 | } | ||
| 814 | } | ||
| 815 | |||
| 816 | fn writeCondBr(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 817 | const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; | ||
| 818 | const extra = w.air.extraData(Air.CondBr, pl_op.payload); | ||
| 819 | const then_body: []const Air.Inst.Index = @ptrCast(w.air.extra.items[extra.end..][0..extra.data.then_body_len]); | ||
| 820 | const else_body: []const Air.Inst.Index = @ptrCast(w.air.extra.items[extra.end + then_body.len ..][0..extra.data.else_body_len]); | ||
| 821 | const liveness_condbr: Air.Liveness.CondBrSlices = if (w.liveness) |liveness| | ||
| 822 | liveness.getCondBr(inst) | ||
| 823 | else | ||
| 824 | .{ .then_deaths = &.{}, .else_deaths = &.{} }; | ||
| 825 | |||
| 826 | try w.writeOperand(s, inst, 0, pl_op.operand); | ||
| 827 | if (w.skip_body) return s.writeAll(", ..."); | ||
| 828 | try s.writeAll(","); | ||
| 829 | if (extra.data.branch_hints.true != .none) { | ||
| 830 | try s.print(" {s}", .{@tagName(extra.data.branch_hints.true)}); | ||
| 831 | } | ||
| 832 | if (extra.data.branch_hints.then_cov != .none) { | ||
| 833 | try s.print(" {s}", .{@tagName(extra.data.branch_hints.then_cov)}); | ||
| 834 | } | ||
| 835 | try s.writeAll(" {\n"); | ||
| 836 | const old_indent = w.indent; | ||
| 837 | w.indent += 2; | ||
| 838 | |||
| 839 | if (liveness_condbr.then_deaths.len != 0) { | ||
| 840 | try s.writeByteNTimes(' ', w.indent); | ||
| 841 | for (liveness_condbr.then_deaths, 0..) |operand, i| { | ||
| 842 | if (i != 0) try s.writeAll(" "); | ||
| 843 | try s.print("{}!", .{operand}); | ||
| 844 | } | ||
| 845 | try s.writeAll("\n"); | ||
| 846 | } | ||
| 847 | |||
| 848 | try w.writeBody(s, then_body); | ||
| 849 | try s.writeByteNTimes(' ', old_indent); | ||
| 850 | try s.writeAll("},"); | ||
| 851 | if (extra.data.branch_hints.false != .none) { | ||
| 852 | try s.print(" {s}", .{@tagName(extra.data.branch_hints.false)}); | ||
| 853 | } | ||
| 854 | if (extra.data.branch_hints.else_cov != .none) { | ||
| 855 | try s.print(" {s}", .{@tagName(extra.data.branch_hints.else_cov)}); | ||
| 856 | } | ||
| 857 | try s.writeAll(" {\n"); | ||
| 858 | |||
| 859 | if (liveness_condbr.else_deaths.len != 0) { | ||
| 860 | try s.writeByteNTimes(' ', w.indent); | ||
| 861 | for (liveness_condbr.else_deaths, 0..) |operand, i| { | ||
| 862 | if (i != 0) try s.writeAll(" "); | ||
| 863 | try s.print("{}!", .{operand}); | ||
| 864 | } | ||
| 865 | try s.writeAll("\n"); | ||
| 866 | } | ||
| 867 | |||
| 868 | try w.writeBody(s, else_body); | ||
| 869 | w.indent = old_indent; | ||
| 870 | |||
| 871 | try s.writeByteNTimes(' ', old_indent); | ||
| 872 | try s.writeAll("}"); | ||
| 873 | } | ||
| 874 | |||
| 875 | fn writeSwitchBr(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 876 | const switch_br = w.air.unwrapSwitch(inst); | ||
| 877 | |||
| 878 | const liveness: Air.Liveness.SwitchBrTable = if (w.liveness) |liveness| | ||
| 879 | liveness.getSwitchBr(w.gpa, inst, switch_br.cases_len + 1) catch | ||
| 880 | @panic("out of memory") | ||
| 881 | else blk: { | ||
| 882 | const slice = w.gpa.alloc([]const Air.Inst.Index, switch_br.cases_len + 1) catch | ||
| 883 | @panic("out of memory"); | ||
| 884 | @memset(slice, &.{}); | ||
| 885 | break :blk .{ .deaths = slice }; | ||
| 886 | }; | ||
| 887 | defer w.gpa.free(liveness.deaths); | ||
| 888 | |||
| 889 | try w.writeOperand(s, inst, 0, switch_br.operand); | ||
| 890 | if (w.skip_body) return s.writeAll(", ..."); | ||
| 891 | const old_indent = w.indent; | ||
| 892 | w.indent += 2; | ||
| 893 | |||
| 894 | var it = switch_br.iterateCases(); | ||
| 895 | while (it.next()) |case| { | ||
| 896 | try s.writeAll(", ["); | ||
| 897 | for (case.items, 0..) |item, item_i| { | ||
| 898 | if (item_i != 0) try s.writeAll(", "); | ||
| 899 | try w.writeInstRef(s, item, false); | ||
| 900 | } | ||
| 901 | for (case.ranges, 0..) |range, range_i| { | ||
| 902 | if (range_i != 0 or case.items.len != 0) try s.writeAll(", "); | ||
| 903 | try w.writeInstRef(s, range[0], false); | ||
| 904 | try s.writeAll("..."); | ||
| 905 | try w.writeInstRef(s, range[1], false); | ||
| 906 | } | ||
| 907 | try s.writeAll("] "); | ||
| 908 | const hint = switch_br.getHint(case.idx); | ||
| 909 | if (hint != .none) { | ||
| 910 | try s.print(".{s} ", .{@tagName(hint)}); | ||
| 911 | } | ||
| 912 | try s.writeAll("=> {\n"); | ||
| 913 | w.indent += 2; | ||
| 914 | |||
| 915 | const deaths = liveness.deaths[case.idx]; | ||
| 916 | if (deaths.len != 0) { | ||
| 917 | try s.writeByteNTimes(' ', w.indent); | ||
| 918 | for (deaths, 0..) |operand, i| { | ||
| 919 | if (i != 0) try s.writeAll(" "); | ||
| 920 | try s.print("{}!", .{operand}); | ||
| 921 | } | ||
| 922 | try s.writeAll("\n"); | ||
| 923 | } | ||
| 924 | |||
| 925 | try w.writeBody(s, case.body); | ||
| 926 | w.indent -= 2; | ||
| 927 | try s.writeByteNTimes(' ', w.indent); | ||
| 928 | try s.writeAll("}"); | ||
| 929 | } | ||
| 930 | |||
| 931 | const else_body = it.elseBody(); | ||
| 932 | if (else_body.len != 0) { | ||
| 933 | try s.writeAll(", else "); | ||
| 934 | const hint = switch_br.getElseHint(); | ||
| 935 | if (hint != .none) { | ||
| 936 | try s.print(".{s} ", .{@tagName(hint)}); | ||
| 937 | } | ||
| 938 | try s.writeAll("=> {\n"); | ||
| 939 | w.indent += 2; | ||
| 940 | |||
| 941 | const deaths = liveness.deaths[liveness.deaths.len - 1]; | ||
| 942 | if (deaths.len != 0) { | ||
| 943 | try s.writeByteNTimes(' ', w.indent); | ||
| 944 | for (deaths, 0..) |operand, i| { | ||
| 945 | if (i != 0) try s.writeAll(" "); | ||
| 946 | try s.print("{}!", .{operand}); | ||
| 947 | } | ||
| 948 | try s.writeAll("\n"); | ||
| 949 | } | ||
| 950 | |||
| 951 | try w.writeBody(s, else_body); | ||
| 952 | w.indent -= 2; | ||
| 953 | try s.writeByteNTimes(' ', w.indent); | ||
| 954 | try s.writeAll("}"); | ||
| 955 | } | ||
| 956 | |||
| 957 | try s.writeAll("\n"); | ||
| 958 | try s.writeByteNTimes(' ', old_indent); | ||
| 959 | } | ||
| 960 | |||
| 961 | fn writeWasmMemorySize(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 962 | const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; | ||
| 963 | try s.print("{d}", .{pl_op.payload}); | ||
| 964 | } | ||
| 965 | |||
| 966 | fn writeWasmMemoryGrow(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 967 | const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; | ||
| 968 | try s.print("{d}, ", .{pl_op.payload}); | ||
| 969 | try w.writeOperand(s, inst, 0, pl_op.operand); | ||
| 970 | } | ||
| 971 | |||
| 972 | fn writeWorkDimension(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 973 | const pl_op = w.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; | ||
| 974 | try s.print("{d}", .{pl_op.payload}); | ||
| 975 | } | ||
| 976 | |||
| 977 | fn writeOperand( | ||
| 978 | w: *Writer, | ||
| 979 | s: anytype, | ||
| 980 | inst: Air.Inst.Index, | ||
| 981 | op_index: usize, | ||
| 982 | operand: Air.Inst.Ref, | ||
| 983 | ) @TypeOf(s).Error!void { | ||
| 984 | const small_tomb_bits = Air.Liveness.bpi - 1; | ||
| 985 | const dies = if (w.liveness) |liveness| blk: { | ||
| 986 | if (op_index < small_tomb_bits) | ||
| 987 | break :blk liveness.operandDies(inst, @intCast(op_index)); | ||
| 988 | var extra_index = liveness.special.get(inst).?; | ||
| 989 | var tomb_op_index: usize = small_tomb_bits; | ||
| 990 | while (true) { | ||
| 991 | const bits = liveness.extra[extra_index]; | ||
| 992 | if (op_index < tomb_op_index + 31) { | ||
| 993 | break :blk @as(u1, @truncate(bits >> @as(u5, @intCast(op_index - tomb_op_index)))) != 0; | ||
| 994 | } | ||
| 995 | if ((bits >> 31) != 0) break :blk false; | ||
| 996 | extra_index += 1; | ||
| 997 | tomb_op_index += 31; | ||
| 998 | } | ||
| 999 | } else false; | ||
| 1000 | return w.writeInstRef(s, operand, dies); | ||
| 1001 | } | ||
| 1002 | |||
| 1003 | fn writeInstRef( | ||
| 1004 | w: *Writer, | ||
| 1005 | s: anytype, | ||
| 1006 | operand: Air.Inst.Ref, | ||
| 1007 | dies: bool, | ||
| 1008 | ) @TypeOf(s).Error!void { | ||
| 1009 | if (@intFromEnum(operand) < InternPool.static_len) { | ||
| 1010 | return s.print("@{}", .{operand}); | ||
| 1011 | } else if (operand.toInterned()) |ip_index| { | ||
| 1012 | const pt = w.pt; | ||
| 1013 | const ty = Type.fromInterned(pt.zcu.intern_pool.indexToKey(ip_index).typeOf()); | ||
| 1014 | try s.print("<{}, {}>", .{ | ||
| 1015 | ty.fmt(pt), | ||
| 1016 | Value.fromInterned(ip_index).fmtValue(pt), | ||
| 1017 | }); | ||
| 1018 | } else { | ||
| 1019 | return w.writeInstIndex(s, operand.toIndex().?, dies); | ||
| 1020 | } | ||
| 1021 | } | ||
| 1022 | |||
| 1023 | fn writeInstIndex( | ||
| 1024 | w: *Writer, | ||
| 1025 | s: anytype, | ||
| 1026 | inst: Air.Inst.Index, | ||
| 1027 | dies: bool, | ||
| 1028 | ) @TypeOf(s).Error!void { | ||
| 1029 | _ = w; | ||
| 1030 | try s.print("{}", .{inst}); | ||
| 1031 | if (dies) try s.writeByte('!'); | ||
| 1032 | } | ||
| 1033 | |||
| 1034 | fn typeOfIndex(w: *Writer, inst: Air.Inst.Index) Type { | ||
| 1035 | const zcu = w.pt.zcu; | ||
| 1036 | return w.air.typeOfIndex(inst, &zcu.intern_pool); | ||
| 1037 | } | ||
| 1038 | }; | ||
test/cases/compile_errors/@import_zon_bad_type.zig+3-3| ... | @@ -117,9 +117,9 @@ export fn testMutablePointer() void { | ... | @@ -117,9 +117,9 @@ export fn testMutablePointer() void { |
| 117 | // tmp.zig:37:38: note: imported here | 117 | // tmp.zig:37:38: note: imported here |
| 118 | // neg_inf.zon:1:1: error: expected type '?u8' | 118 | // neg_inf.zon:1:1: error: expected type '?u8' |
| 119 | // tmp.zig:57:28: note: imported here | 119 | // tmp.zig:57:28: note: imported here |
| 120 | // neg_inf.zon:1:1: error: expected type 'tmp.testNonExhaustiveEnum__enum_522' | 120 | // neg_inf.zon:1:1: error: expected type 'tmp.testNonExhaustiveEnum__enum_525' |
| 121 | // tmp.zig:62:39: note: imported here | 121 | // tmp.zig:62:39: note: imported here |
| 122 | // neg_inf.zon:1:1: error: expected type 'tmp.testUntaggedUnion__union_524' | 122 | // neg_inf.zon:1:1: error: expected type 'tmp.testUntaggedUnion__union_527' |
| 123 | // tmp.zig:67:44: note: imported here | 123 | // tmp.zig:67:44: note: imported here |
| 124 | // neg_inf.zon:1:1: error: expected type 'tmp.testTaggedUnionVoid__union_527' | 124 | // neg_inf.zon:1:1: error: expected type 'tmp.testTaggedUnionVoid__union_530' |
| 125 | // tmp.zig:72:50: note: imported here | 125 | // tmp.zig:72:50: note: imported here |
test/cases/compile_errors/anytype_param_requires_comptime.zig+1-1| ... | @@ -15,6 +15,6 @@ pub export fn entry() void { | ... | @@ -15,6 +15,6 @@ pub export fn entry() void { |
| 15 | // error | 15 | // error |
| 16 | // | 16 | // |
| 17 | // :7:25: error: unable to resolve comptime value | 17 | // :7:25: error: unable to resolve comptime value |
| 18 | // :7:25: note: initializer of comptime-only struct 'tmp.S.foo__anon_496.C' must be comptime-known | 18 | // :7:25: note: initializer of comptime-only struct 'tmp.S.foo__anon_499.C' must be comptime-known |
| 19 | // :4:16: note: struct requires comptime because of this field | 19 | // :4:16: note: struct requires comptime because of this field |
| 20 | // :4:16: note: types are not available at runtime | 20 | // :4:16: note: types are not available at runtime |
test/cases/compile_errors/bogus_method_call_on_slice.zig+1-1| ... | @@ -16,5 +16,5 @@ pub export fn entry2() void { | ... | @@ -16,5 +16,5 @@ pub export fn entry2() void { |
| 16 | // | 16 | // |
| 17 | // :3:6: error: no field or member function named 'copy' in '[]const u8' | 17 | // :3:6: error: no field or member function named 'copy' in '[]const u8' |
| 18 | // :9:8: error: no field or member function named 'bar' in '@TypeOf(.{})' | 18 | // :9:8: error: no field or member function named 'bar' in '@TypeOf(.{})' |
| 19 | // :12:18: error: no field or member function named 'bar' in 'tmp.entry2__struct_500' | 19 | // :12:18: error: no field or member function named 'bar' in 'tmp.entry2__struct_503' |
| 20 | // :12:6: note: struct declared here | 20 | // :12:6: note: struct declared here |
test/cases/compile_errors/coerce_anon_struct.zig+1-1| ... | @@ -6,6 +6,6 @@ export fn foo() void { | ... | @@ -6,6 +6,6 @@ export fn foo() void { |
| 6 | 6 | ||
| 7 | // error | 7 | // error |
| 8 | // | 8 | // |
| 9 | // :4:16: error: expected type 'tmp.T', found 'tmp.foo__struct_489' | 9 | // :4:16: error: expected type 'tmp.T', found 'tmp.foo__struct_492' |
| 10 | // :3:16: note: struct declared here | 10 | // :3:16: note: struct declared here |
| 11 | // :1:11: note: struct declared here | 11 | // :1:11: note: struct declared here |
test/cases/compile_errors/redundant_try.zig+2-2| ... | @@ -44,9 +44,9 @@ comptime { | ... | @@ -44,9 +44,9 @@ comptime { |
| 44 | // | 44 | // |
| 45 | // :5:23: error: expected error union type, found 'comptime_int' | 45 | // :5:23: error: expected error union type, found 'comptime_int' |
| 46 | // :10:23: error: expected error union type, found '@TypeOf(.{})' | 46 | // :10:23: error: expected error union type, found '@TypeOf(.{})' |
| 47 | // :15:23: error: expected error union type, found 'tmp.test2__struct_526' | 47 | // :15:23: error: expected error union type, found 'tmp.test2__struct_529' |
| 48 | // :15:23: note: struct declared here | 48 | // :15:23: note: struct declared here |
| 49 | // :20:27: error: expected error union type, found 'tmp.test3__struct_528' | 49 | // :20:27: error: expected error union type, found 'tmp.test3__struct_531' |
| 50 | // :20:27: note: struct declared here | 50 | // :20:27: note: struct declared here |
| 51 | // :25:23: error: expected error union type, found 'struct { comptime *const [5:0]u8 = "hello" }' | 51 | // :25:23: error: expected error union type, found 'struct { comptime *const [5:0]u8 = "hello" }' |
| 52 | // :31:13: error: expected error union type, found 'u32' | 52 | // :31:13: error: expected error union type, found 'u32' |
test/tests.zig+5-4| ... | @@ -1598,7 +1598,9 @@ const c_abi_targets = blk: { | ... | @@ -1598,7 +1598,9 @@ const c_abi_targets = blk: { |
| 1598 | break :blk [_]CAbiTarget{ | 1598 | break :blk [_]CAbiTarget{ |
| 1599 | // Native Targets | 1599 | // Native Targets |
| 1600 | 1600 | ||
| 1601 | .{}, | 1601 | .{ |
| 1602 | .use_llvm = true, | ||
| 1603 | }, | ||
| 1602 | 1604 | ||
| 1603 | // Linux Targets | 1605 | // Linux Targets |
| 1604 | 1606 | ||
| ... | @@ -1837,7 +1839,6 @@ const c_abi_targets = blk: { | ... | @@ -1837,7 +1839,6 @@ const c_abi_targets = blk: { |
| 1837 | .abi = .musl, | 1839 | .abi = .musl, |
| 1838 | }, | 1840 | }, |
| 1839 | .use_llvm = false, | 1841 | .use_llvm = false, |
| 1840 | .use_lld = false, | ||
| 1841 | .c_defines = &.{"ZIG_BACKEND_STAGE2_X86_64"}, | 1842 | .c_defines = &.{"ZIG_BACKEND_STAGE2_X86_64"}, |
| 1842 | }, | 1843 | }, |
| 1843 | .{ | 1844 | .{ |
| ... | @@ -1848,7 +1849,6 @@ const c_abi_targets = blk: { | ... | @@ -1848,7 +1849,6 @@ const c_abi_targets = blk: { |
| 1848 | .abi = .musl, | 1849 | .abi = .musl, |
| 1849 | }, | 1850 | }, |
| 1850 | .use_llvm = false, | 1851 | .use_llvm = false, |
| 1851 | .use_lld = false, | ||
| 1852 | .strip = true, | 1852 | .strip = true, |
| 1853 | .c_defines = &.{"ZIG_BACKEND_STAGE2_X86_64"}, | 1853 | .c_defines = &.{"ZIG_BACKEND_STAGE2_X86_64"}, |
| 1854 | }, | 1854 | }, |
| ... | @@ -1860,7 +1860,6 @@ const c_abi_targets = blk: { | ... | @@ -1860,7 +1860,6 @@ const c_abi_targets = blk: { |
| 1860 | .abi = .musl, | 1860 | .abi = .musl, |
| 1861 | }, | 1861 | }, |
| 1862 | .use_llvm = false, | 1862 | .use_llvm = false, |
| 1863 | .use_lld = false, | ||
| 1864 | .pic = true, | 1863 | .pic = true, |
| 1865 | .c_defines = &.{"ZIG_BACKEND_STAGE2_X86_64"}, | 1864 | .c_defines = &.{"ZIG_BACKEND_STAGE2_X86_64"}, |
| 1866 | }, | 1865 | }, |
| ... | @@ -1870,6 +1869,7 @@ const c_abi_targets = blk: { | ... | @@ -1870,6 +1869,7 @@ const c_abi_targets = blk: { |
| 1870 | .os_tag = .linux, | 1869 | .os_tag = .linux, |
| 1871 | .abi = .musl, | 1870 | .abi = .musl, |
| 1872 | }, | 1871 | }, |
| 1872 | .use_llvm = true, | ||
| 1873 | }, | 1873 | }, |
| 1874 | .{ | 1874 | .{ |
| 1875 | .target = .{ | 1875 | .target = .{ |
| ... | @@ -1877,6 +1877,7 @@ const c_abi_targets = blk: { | ... | @@ -1877,6 +1877,7 @@ const c_abi_targets = blk: { |
| 1877 | .os_tag = .linux, | 1877 | .os_tag = .linux, |
| 1878 | .abi = .muslx32, | 1878 | .abi = .muslx32, |
| 1879 | }, | 1879 | }, |
| 1880 | .use_llvm = true, | ||
| 1880 | }, | 1881 | }, |
| 1881 | 1882 | ||
| 1882 | // WASI Targets | 1883 | // WASI Targets |