| 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 | 519 | src/Air/Legalize.zig |
| 520 | 520 | src/Air/Liveness.zig |
| 521 | 521 | src/Air/Liveness/Verify.zig |
| 522 | src/Air/print.zig | |
| 522 | 523 | src/Air/types_resolved.zig |
| 523 | 524 | src/Builtin.zig |
| 524 | 525 | src/Compilation.zig |
| ... | ... | @@ -675,7 +676,6 @@ set(ZIG_STAGE2_SOURCES |
| 675 | 676 | src/libs/mingw.zig |
| 676 | 677 | src/libs/musl.zig |
| 677 | 678 | src/mutable_value.zig |
| 678 | src/print_air.zig | |
| 679 | 679 | src/print_env.zig |
| 680 | 680 | src/print_targets.zig |
| 681 | 681 | src/print_value.zig |
lib/std/builtin.zig+13-2| ... | ... | @@ -61,7 +61,7 @@ pub const StackTrace = struct { |
| 61 | 61 | |
| 62 | 62 | /// This data structure is used by the Zig language code generation and |
| 63 | 63 | /// therefore must be kept in sync with the compiler implementation. |
| 64 | pub const GlobalLinkage = enum { | |
| 64 | pub const GlobalLinkage = enum(u2) { | |
| 65 | 65 | internal, |
| 66 | 66 | strong, |
| 67 | 67 | weak, |
| ... | ... | @@ -70,7 +70,7 @@ pub const GlobalLinkage = enum { |
| 70 | 70 | |
| 71 | 71 | /// This data structure is used by the Zig language code generation and |
| 72 | 72 | /// therefore must be kept in sync with the compiler implementation. |
| 73 | pub const SymbolVisibility = enum { | |
| 73 | pub const SymbolVisibility = enum(u2) { | |
| 74 | 74 | default, |
| 75 | 75 | hidden, |
| 76 | 76 | protected, |
| ... | ... | @@ -1030,8 +1030,19 @@ pub const ExternOptions = struct { |
| 1030 | 1030 | name: []const u8, |
| 1031 | 1031 | library_name: ?[]const u8 = null, |
| 1032 | 1032 | linkage: GlobalLinkage = .strong, |
| 1033 | visibility: SymbolVisibility = .default, | |
| 1034 | /// Setting this to `true` makes the `@extern` a runtime value. | |
| 1033 | 1035 | is_thread_local: bool = false, |
| 1034 | 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 | 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 | 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 | |
| 87 | /// helper function. | |
| 88 | pub fn get_DYNAMIC() ?[*]elf.Dyn { | |
| 89 | return @extern([*]elf.Dyn, .{ .name = "_DYNAMIC", .linkage = .weak }); | |
| 86 | /// TODO fix comparisons of extern symbol pointers so we don't need this helper function. | |
| 87 | pub fn get_DYNAMIC() ?[*]const elf.Dyn { | |
| 88 | return @extern([*]const elf.Dyn, .{ | |
| 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 | 96 | _ = phdrs; |
| 94 | 97 | const _DYNAMIC = get_DYNAMIC() orelse { |
| 95 | 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 | 39 | // Obtain a pointer to the _DYNAMIC array. |
| 40 | 40 | // We have to compute its address as a PC-relative quantity not to require a |
| 41 | 41 | // relocation that, at this point, is not yet applied. |
| 42 | inline fn getDynamicSymbol() [*]elf.Dyn { | |
| 43 | return switch (builtin.cpu.arch) { | |
| 44 | .x86 => asm volatile ( | |
| 45 | \\ .weak _DYNAMIC | |
| 46 | \\ .hidden _DYNAMIC | |
| 47 | \\ call 1f | |
| 48 | \\ 1: pop %[ret] | |
| 49 | \\ lea _DYNAMIC-1b(%[ret]), %[ret] | |
| 50 | : [ret] "=r" (-> [*]elf.Dyn), | |
| 51 | ), | |
| 52 | .x86_64 => asm volatile ( | |
| 53 | \\ .weak _DYNAMIC | |
| 54 | \\ .hidden _DYNAMIC | |
| 55 | \\ lea _DYNAMIC(%%rip), %[ret] | |
| 56 | : [ret] "=r" (-> [*]elf.Dyn), | |
| 57 | ), | |
| 58 | .arc => asm volatile ( | |
| 59 | \\ .weak _DYNAMIC | |
| 60 | \\ .hidden _DYNAMIC | |
| 61 | \\ add %[ret], pcl, _DYNAMIC@pcl | |
| 62 | : [ret] "=r" (-> [*]elf.Dyn), | |
| 63 | ), | |
| 64 | // Work around the limited offset range of `ldr` | |
| 65 | .arm, .armeb, .thumb, .thumbeb => asm volatile ( | |
| 66 | \\ .weak _DYNAMIC | |
| 67 | \\ .hidden _DYNAMIC | |
| 68 | \\ ldr %[ret], 1f | |
| 69 | \\ add %[ret], pc | |
| 70 | \\ b 2f | |
| 71 | \\ 1: .word _DYNAMIC-1b | |
| 72 | \\ 2: | |
| 73 | : [ret] "=r" (-> [*]elf.Dyn), | |
| 74 | ), | |
| 75 | // A simple `adr` is not enough as it has a limited offset range | |
| 76 | .aarch64, .aarch64_be => asm volatile ( | |
| 77 | \\ .weak _DYNAMIC | |
| 78 | \\ .hidden _DYNAMIC | |
| 79 | \\ adrp %[ret], _DYNAMIC | |
| 80 | \\ add %[ret], %[ret], #:lo12:_DYNAMIC | |
| 81 | : [ret] "=r" (-> [*]elf.Dyn), | |
| 82 | ), | |
| 83 | // The CSKY ABI requires the gb register to point to the GOT. Additionally, the first | |
| 84 | // entry in the GOT is defined to hold the address of _DYNAMIC. | |
| 85 | .csky => asm volatile ( | |
| 86 | \\ mov %[ret], gb | |
| 87 | \\ ldw %[ret], %[ret] | |
| 88 | : [ret] "=r" (-> [*]elf.Dyn), | |
| 89 | ), | |
| 90 | .hexagon => asm volatile ( | |
| 91 | \\ .weak _DYNAMIC | |
| 92 | \\ .hidden _DYNAMIC | |
| 93 | \\ jump 1f | |
| 94 | \\ .word _DYNAMIC - . | |
| 95 | \\ 1: | |
| 96 | \\ r1 = pc | |
| 97 | \\ r1 = add(r1, #-4) | |
| 98 | \\ %[ret] = memw(r1) | |
| 99 | \\ %[ret] = add(r1, %[ret]) | |
| 100 | : [ret] "=r" (-> [*]elf.Dyn), | |
| 101 | : | |
| 102 | : "r1" | |
| 103 | ), | |
| 104 | .loongarch32, .loongarch64 => asm volatile ( | |
| 105 | \\ .weak _DYNAMIC | |
| 106 | \\ .hidden _DYNAMIC | |
| 107 | \\ la.local %[ret], _DYNAMIC | |
| 108 | : [ret] "=r" (-> [*]elf.Dyn), | |
| 109 | ), | |
| 110 | // Note that the - 8 is needed because pc in the second lea instruction points into the | |
| 111 | // middle of that instruction. (The first lea is 6 bytes, the second is 4 bytes.) | |
| 112 | .m68k => asm volatile ( | |
| 113 | \\ .weak _DYNAMIC | |
| 114 | \\ .hidden _DYNAMIC | |
| 115 | \\ lea _DYNAMIC - . - 8, %[ret] | |
| 116 | \\ lea (%[ret], %%pc), %[ret] | |
| 117 | : [ret] "=r" (-> [*]elf.Dyn), | |
| 118 | ), | |
| 119 | .mips, .mipsel => asm volatile ( | |
| 120 | \\ .weak _DYNAMIC | |
| 121 | \\ .hidden _DYNAMIC | |
| 122 | \\ bal 1f | |
| 123 | \\ .gpword _DYNAMIC | |
| 124 | \\ 1: | |
| 125 | \\ lw %[ret], 0($ra) | |
| 126 | \\ addu %[ret], %[ret], $gp | |
| 127 | : [ret] "=r" (-> [*]elf.Dyn), | |
| 128 | : | |
| 129 | : "lr" | |
| 130 | ), | |
| 131 | .mips64, .mips64el => asm volatile ( | |
| 132 | \\ .weak _DYNAMIC | |
| 133 | \\ .hidden _DYNAMIC | |
| 134 | \\ .balign 8 | |
| 135 | \\ bal 1f | |
| 136 | \\ .gpdword _DYNAMIC | |
| 137 | \\ 1: | |
| 138 | \\ ld %[ret], 0($ra) | |
| 139 | \\ daddu %[ret], %[ret], $gp | |
| 140 | : [ret] "=r" (-> [*]elf.Dyn), | |
| 141 | : | |
| 142 | : "lr" | |
| 143 | ), | |
| 144 | .powerpc, .powerpcle => asm volatile ( | |
| 145 | \\ .weak _DYNAMIC | |
| 146 | \\ .hidden _DYNAMIC | |
| 147 | \\ bl 1f | |
| 148 | \\ .long _DYNAMIC - . | |
| 149 | \\ 1: | |
| 150 | \\ mflr %[ret] | |
| 151 | \\ lwz 4, 0(%[ret]) | |
| 152 | \\ add %[ret], 4, %[ret] | |
| 153 | : [ret] "=r" (-> [*]elf.Dyn), | |
| 154 | : | |
| 155 | : "lr", "r4" | |
| 156 | ), | |
| 157 | .powerpc64, .powerpc64le => asm volatile ( | |
| 158 | \\ .weak _DYNAMIC | |
| 159 | \\ .hidden _DYNAMIC | |
| 160 | \\ bl 1f | |
| 161 | \\ .quad _DYNAMIC - . | |
| 162 | \\ 1: | |
| 163 | \\ mflr %[ret] | |
| 164 | \\ ld 4, 0(%[ret]) | |
| 165 | \\ add %[ret], 4, %[ret] | |
| 166 | : [ret] "=r" (-> [*]elf.Dyn), | |
| 167 | : | |
| 168 | : "lr", "r4" | |
| 169 | ), | |
| 170 | .riscv32, .riscv64 => asm volatile ( | |
| 171 | \\ .weak _DYNAMIC | |
| 172 | \\ .hidden _DYNAMIC | |
| 173 | \\ lla %[ret], _DYNAMIC | |
| 174 | : [ret] "=r" (-> [*]elf.Dyn), | |
| 175 | ), | |
| 176 | .s390x => asm volatile ( | |
| 177 | \\ .weak _DYNAMIC | |
| 178 | \\ .hidden _DYNAMIC | |
| 179 | \\ larl %[ret], 1f | |
| 180 | \\ ag %[ret], 0(%[ret]) | |
| 181 | \\ jg 2f | |
| 182 | \\ 1: .quad _DYNAMIC - . | |
| 183 | \\ 2: | |
| 184 | : [ret] "=r" (-> [*]elf.Dyn), | |
| 185 | ), | |
| 186 | // The compiler does not necessarily have any obligation to load the `l7` register (pointing | |
| 187 | // to the GOT), so do it ourselves just in case. | |
| 188 | .sparc, .sparc64 => asm volatile ( | |
| 189 | \\ sethi %%hi(_GLOBAL_OFFSET_TABLE_ - 4), %%l7 | |
| 190 | \\ call 1f | |
| 191 | \\ add %%l7, %%lo(_GLOBAL_OFFSET_TABLE_ + 4), %%l7 | |
| 192 | \\ 1: | |
| 193 | \\ add %%l7, %%o7, %[ret] | |
| 194 | : [ret] "=r" (-> [*]elf.Dyn), | |
| 195 | ), | |
| 196 | else => { | |
| 197 | @compileError("PIE startup is not yet supported for this target!"); | |
| 42 | inline fn getDynamicSymbol() [*]const elf.Dyn { | |
| 43 | return switch (builtin.zig_backend) { | |
| 44 | else => switch (builtin.cpu.arch) { | |
| 45 | .x86 => asm volatile ( | |
| 46 | \\ .weak _DYNAMIC | |
| 47 | \\ .hidden _DYNAMIC | |
| 48 | \\ call 1f | |
| 49 | \\ 1: pop %[ret] | |
| 50 | \\ lea _DYNAMIC-1b(%[ret]), %[ret] | |
| 51 | : [ret] "=r" (-> [*]const elf.Dyn), | |
| 52 | ), | |
| 53 | .x86_64 => asm volatile ( | |
| 54 | \\ .weak _DYNAMIC | |
| 55 | \\ .hidden _DYNAMIC | |
| 56 | \\ lea _DYNAMIC(%%rip), %[ret] | |
| 57 | : [ret] "=r" (-> [*]const elf.Dyn), | |
| 58 | ), | |
| 59 | .arc => asm volatile ( | |
| 60 | \\ .weak _DYNAMIC | |
| 61 | \\ .hidden _DYNAMIC | |
| 62 | \\ add %[ret], pcl, _DYNAMIC@pcl | |
| 63 | : [ret] "=r" (-> [*]const elf.Dyn), | |
| 64 | ), | |
| 65 | // Work around the limited offset range of `ldr` | |
| 66 | .arm, .armeb, .thumb, .thumbeb => asm volatile ( | |
| 67 | \\ .weak _DYNAMIC | |
| 68 | \\ .hidden _DYNAMIC | |
| 69 | \\ ldr %[ret], 1f | |
| 70 | \\ add %[ret], pc | |
| 71 | \\ b 2f | |
| 72 | \\ 1: .word _DYNAMIC-1b | |
| 73 | \\ 2: | |
| 74 | : [ret] "=r" (-> [*]const elf.Dyn), | |
| 75 | ), | |
| 76 | // A simple `adr` is not enough as it has a limited offset range | |
| 77 | .aarch64, .aarch64_be => asm volatile ( | |
| 78 | \\ .weak _DYNAMIC | |
| 79 | \\ .hidden _DYNAMIC | |
| 80 | \\ adrp %[ret], _DYNAMIC | |
| 81 | \\ add %[ret], %[ret], #:lo12:_DYNAMIC | |
| 82 | : [ret] "=r" (-> [*]const elf.Dyn), | |
| 83 | ), | |
| 84 | // The CSKY ABI requires the gb register to point to the GOT. Additionally, the first | |
| 85 | // entry in the GOT is defined to hold the address of _DYNAMIC. | |
| 86 | .csky => asm volatile ( | |
| 87 | \\ mov %[ret], gb | |
| 88 | \\ ldw %[ret], %[ret] | |
| 89 | : [ret] "=r" (-> [*]const elf.Dyn), | |
| 90 | ), | |
| 91 | .hexagon => asm volatile ( | |
| 92 | \\ .weak _DYNAMIC | |
| 93 | \\ .hidden _DYNAMIC | |
| 94 | \\ jump 1f | |
| 95 | \\ .word _DYNAMIC - . | |
| 96 | \\ 1: | |
| 97 | \\ r1 = pc | |
| 98 | \\ r1 = add(r1, #-4) | |
| 99 | \\ %[ret] = memw(r1) | |
| 100 | \\ %[ret] = add(r1, %[ret]) | |
| 101 | : [ret] "=r" (-> [*]const elf.Dyn), | |
| 102 | : | |
| 103 | : "r1" | |
| 104 | ), | |
| 105 | .loongarch32, .loongarch64 => asm volatile ( | |
| 106 | \\ .weak _DYNAMIC | |
| 107 | \\ .hidden _DYNAMIC | |
| 108 | \\ la.local %[ret], _DYNAMIC | |
| 109 | : [ret] "=r" (-> [*]const elf.Dyn), | |
| 110 | ), | |
| 111 | // Note that the - 8 is needed because pc in the second lea instruction points into the | |
| 112 | // middle of that instruction. (The first lea is 6 bytes, the second is 4 bytes.) | |
| 113 | .m68k => asm volatile ( | |
| 114 | \\ .weak _DYNAMIC | |
| 115 | \\ .hidden _DYNAMIC | |
| 116 | \\ lea _DYNAMIC - . - 8, %[ret] | |
| 117 | \\ lea (%[ret], %%pc), %[ret] | |
| 118 | : [ret] "=r" (-> [*]const elf.Dyn), | |
| 119 | ), | |
| 120 | .mips, .mipsel => asm volatile ( | |
| 121 | \\ .weak _DYNAMIC | |
| 122 | \\ .hidden _DYNAMIC | |
| 123 | \\ bal 1f | |
| 124 | \\ .gpword _DYNAMIC | |
| 125 | \\ 1: | |
| 126 | \\ lw %[ret], 0($ra) | |
| 127 | \\ addu %[ret], %[ret], $gp | |
| 128 | : [ret] "=r" (-> [*]const elf.Dyn), | |
| 129 | : | |
| 130 | : "lr" | |
| 131 | ), | |
| 132 | .mips64, .mips64el => asm volatile ( | |
| 133 | \\ .weak _DYNAMIC | |
| 134 | \\ .hidden _DYNAMIC | |
| 135 | \\ .balign 8 | |
| 136 | \\ bal 1f | |
| 137 | \\ .gpdword _DYNAMIC | |
| 138 | \\ 1: | |
| 139 | \\ ld %[ret], 0($ra) | |
| 140 | \\ daddu %[ret], %[ret], $gp | |
| 141 | : [ret] "=r" (-> [*]const elf.Dyn), | |
| 142 | : | |
| 143 | : "lr" | |
| 144 | ), | |
| 145 | .powerpc, .powerpcle => asm volatile ( | |
| 146 | \\ .weak _DYNAMIC | |
| 147 | \\ .hidden _DYNAMIC | |
| 148 | \\ bl 1f | |
| 149 | \\ .long _DYNAMIC - . | |
| 150 | \\ 1: | |
| 151 | \\ mflr %[ret] | |
| 152 | \\ lwz 4, 0(%[ret]) | |
| 153 | \\ add %[ret], 4, %[ret] | |
| 154 | : [ret] "=r" (-> [*]const elf.Dyn), | |
| 155 | : | |
| 156 | : "lr", "r4" | |
| 157 | ), | |
| 158 | .powerpc64, .powerpc64le => asm volatile ( | |
| 159 | \\ .weak _DYNAMIC | |
| 160 | \\ .hidden _DYNAMIC | |
| 161 | \\ bl 1f | |
| 162 | \\ .quad _DYNAMIC - . | |
| 163 | \\ 1: | |
| 164 | \\ mflr %[ret] | |
| 165 | \\ ld 4, 0(%[ret]) | |
| 166 | \\ add %[ret], 4, %[ret] | |
| 167 | : [ret] "=r" (-> [*]const elf.Dyn), | |
| 168 | : | |
| 169 | : "lr", "r4" | |
| 170 | ), | |
| 171 | .riscv32, .riscv64 => asm volatile ( | |
| 172 | \\ .weak _DYNAMIC | |
| 173 | \\ .hidden _DYNAMIC | |
| 174 | \\ lla %[ret], _DYNAMIC | |
| 175 | : [ret] "=r" (-> [*]const elf.Dyn), | |
| 176 | ), | |
| 177 | .s390x => asm volatile ( | |
| 178 | \\ .weak _DYNAMIC | |
| 179 | \\ .hidden _DYNAMIC | |
| 180 | \\ larl %[ret], 1f | |
| 181 | \\ ag %[ret], 0(%[ret]) | |
| 182 | \\ jg 2f | |
| 183 | \\ 1: .quad _DYNAMIC - . | |
| 184 | \\ 2: | |
| 185 | : [ret] "=r" (-> [*]const elf.Dyn), | |
| 186 | ), | |
| 187 | // The compiler does not necessarily have any obligation to load the `l7` register (pointing | |
| 188 | // to the GOT), so do it ourselves just in case. | |
| 189 | .sparc, .sparc64 => asm volatile ( | |
| 190 | \\ sethi %%hi(_GLOBAL_OFFSET_TABLE_ - 4), %%l7 | |
| 191 | \\ call 1f | |
| 192 | \\ add %%l7, %%lo(_GLOBAL_OFFSET_TABLE_ + 4), %%l7 | |
| 193 | \\ 1: | |
| 194 | \\ add %%l7, %%o7, %[ret] | |
| 195 | : [ret] "=r" (-> [*]const elf.Dyn), | |
| 196 | ), | |
| 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 | 211 | @setRuntimeSafety(false); |
| 204 | 212 | @disableInstrumentation(); |
| 205 | 213 | |
| ... | ... | @@ -256,10 +264,9 @@ pub fn relocate(phdrs: []elf.Phdr) void { |
| 256 | 264 | |
| 257 | 265 | const rel = sorted_dynv[elf.DT_REL]; |
| 258 | 266 | if (rel != 0) { |
| 259 | const rels = @call(.always_inline, std.mem.bytesAsSlice, .{ | |
| 260 | elf.Rel, | |
| 261 | @as([*]u8, @ptrFromInt(base_addr + rel))[0..sorted_dynv[elf.DT_RELSZ]], | |
| 262 | }); | |
| 267 | const rels: []const elf.Rel = @alignCast(@ptrCast( | |
| 268 | @as([*]align(@alignOf(elf.Rel)) const u8, @ptrFromInt(base_addr + rel))[0..sorted_dynv[elf.DT_RELSZ]], | |
| 269 | )); | |
| 263 | 270 | for (rels) |r| { |
| 264 | 271 | if (r.r_type() != R_RELATIVE) continue; |
| 265 | 272 | @as(*usize, @ptrFromInt(base_addr + r.r_offset)).* += base_addr; |
| ... | ... | @@ -268,10 +275,9 @@ pub fn relocate(phdrs: []elf.Phdr) void { |
| 268 | 275 | |
| 269 | 276 | const rela = sorted_dynv[elf.DT_RELA]; |
| 270 | 277 | if (rela != 0) { |
| 271 | const relas = @call(.always_inline, std.mem.bytesAsSlice, .{ | |
| 272 | elf.Rela, | |
| 273 | @as([*]u8, @ptrFromInt(base_addr + rela))[0..sorted_dynv[elf.DT_RELASZ]], | |
| 274 | }); | |
| 278 | const relas: []const elf.Rela = @alignCast(@ptrCast( | |
| 279 | @as([*]align(@alignOf(elf.Rela)) const u8, @ptrFromInt(base_addr + rela))[0..sorted_dynv[elf.DT_RELASZ]], | |
| 280 | )); | |
| 275 | 281 | for (relas) |r| { |
| 276 | 282 | if (r.r_type() != R_RELATIVE) continue; |
| 277 | 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 | 286 | |
| 281 | 287 | const relr = sorted_dynv[elf.DT_RELR]; |
| 282 | 288 | if (relr != 0) { |
| 283 | const relrs = @call(.always_inline, std.mem.bytesAsSlice, .{ | |
| 284 | elf.Relr, | |
| 285 | @as([*]u8, @ptrFromInt(base_addr + relr))[0..sorted_dynv[elf.DT_RELRSZ]], | |
| 286 | }); | |
| 289 | const relrs: []const elf.Relr = @ptrCast( | |
| 290 | @as([*]align(@alignOf(elf.Relr)) const u8, @ptrFromInt(base_addr + relr))[0..sorted_dynv[elf.DT_RELRSZ]], | |
| 291 | ); | |
| 287 | 292 | var current: [*]usize = undefined; |
| 288 | 293 | for (relrs) |r| { |
| 289 | 294 | if ((r & 1) == 0) { |
lib/std/start.zig+6-6| ... | ... | @@ -163,7 +163,7 @@ fn exit2(code: usize) noreturn { |
| 163 | 163 | // exits(0) |
| 164 | 164 | .plan9 => std.os.plan9.exits(null), |
| 165 | 165 | .windows => { |
| 166 | std.os.windows.ntdll.RtlExitUserProcess(@as(u32, @truncate(code))); | |
| 166 | std.os.windows.ntdll.RtlExitUserProcess(@truncate(code)); | |
| 167 | 167 | }, |
| 168 | 168 | else => @compileError("TODO"), |
| 169 | 169 | } |
| ... | ... | @@ -511,7 +511,7 @@ fn posixCallMainAndExit(argc_argv_ptr: [*]usize) callconv(.c) noreturn { |
| 511 | 511 | // Code coverage instrumentation might try to use thread local variables. |
| 512 | 512 | @disableInstrumentation(); |
| 513 | 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 | 516 | const envp_optional: [*:null]?[*:0]u8 = @ptrCast(@alignCast(argv + argc + 1)); |
| 517 | 517 | var envp_count: usize = 0; |
| ... | ... | @@ -573,11 +573,11 @@ fn posixCallMainAndExit(argc_argv_ptr: [*]usize) callconv(.c) noreturn { |
| 573 | 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 | 577 | .name = "__init_array_start", |
| 578 | 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 | 581 | .name = "__init_array_end", |
| 582 | 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 | 651 | } |
| 652 | 652 | |
| 653 | 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 | 655 | return callMain(); |
| 656 | 656 | } |
| 657 | 657 | |
| ... | ... | @@ -701,7 +701,7 @@ pub inline fn callMain() u8 { |
| 701 | 701 | pub fn call_wWinMain() std.os.windows.INT { |
| 702 | 702 | const peb = std.os.windows.peb(); |
| 703 | 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 | 705 | const lpCmdLine: [*:0]u16 = @ptrCast(peb.ProcessParameters.CommandLine.Buffer); |
| 706 | 706 | |
| 707 | 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 | 1823 | hidden = 1, |
| 1824 | 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 | 1834 | pub fn format( |
| 1827 | 1835 | self: Visibility, |
| 1828 | 1836 | comptime _: []const u8, |
| ... | ... | @@ -2555,6 +2563,10 @@ pub const Variable = struct { |
| 2555 | 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 | 2570 | pub fn setDllStorageClass(self: Index, class: DllStorageClass, builder: *Builder) void { |
| 2559 | 2571 | return self.ptrConst(builder).global.setDllStorageClass(class, builder); |
| 2560 | 2572 | } |
lib/zig.h+9| ... | ... | @@ -272,6 +272,15 @@ |
| 272 | 272 | #define zig_linksection_fn zig_linksection |
| 273 | 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 | 284 | #if zig_has_builtin(unreachable) || defined(zig_gcc) || defined(zig_tinyc) |
| 276 | 285 | #define zig_unreachable() __builtin_unreachable() |
| 277 | 286 | #elif defined(zig_msvc) |
src/Air.zig+10-4| ... | ... | @@ -13,6 +13,7 @@ const InternPool = @import("InternPool.zig"); |
| 13 | 13 | const Type = @import("Type.zig"); |
| 14 | 14 | const Value = @import("Value.zig"); |
| 15 | 15 | const Zcu = @import("Zcu.zig"); |
| 16 | const print = @import("Air/print.zig"); | |
| 16 | 17 | const types_resolved = @import("Air/types_resolved.zig"); |
| 17 | 18 | |
| 18 | 19 | pub const Legalize = @import("Air/Legalize.zig"); |
| ... | ... | @@ -863,16 +864,17 @@ pub const Inst = struct { |
| 863 | 864 | /// Uses the `vector_store_elem` field. |
| 864 | 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 | 869 | /// * `threadlocal var` |
| 869 | 870 | /// * `extern threadlocal var` (or corresponding `@extern`) |
| 870 | 871 | /// * `@extern` with `.is_dll_import = true` |
| 872 | /// * `@extern` with `.relocation = .pcrel` | |
| 871 | 873 | /// |
| 872 | 874 | /// Such pointers are runtime values, so cannot be represented with an InternPool index. |
| 873 | 875 | /// |
| 874 | 876 | /// Uses the `ty_nav` field. |
| 875 | tlv_dllimport_ptr, | |
| 877 | runtime_nav_ptr, | |
| 876 | 878 | |
| 877 | 879 | /// Implements @cVaArg builtin. |
| 878 | 880 | /// Uses the `ty_op` field. |
| ... | ... | @@ -1708,7 +1710,7 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool) |
| 1708 | 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 | 1715 | .work_item_id, |
| 1714 | 1716 | .work_group_size, |
| ... | ... | @@ -1983,7 +1985,7 @@ pub fn mustLower(air: Air, inst: Air.Inst.Index, ip: *const InternPool) bool { |
| 1983 | 1985 | .err_return_trace, |
| 1984 | 1986 | .addrspace_cast, |
| 1985 | 1987 | .save_err_return_trace_index, |
| 1986 | .tlv_dllimport_ptr, | |
| 1988 | .runtime_nav_ptr, | |
| 1987 | 1989 | .work_item_id, |
| 1988 | 1990 | .work_group_size, |
| 1989 | 1991 | .work_group_id, |
| ... | ... | @@ -2141,6 +2143,10 @@ pub const typesFullyResolved = types_resolved.typesFullyResolved; |
| 2141 | 2143 | pub const typeFullyResolved = types_resolved.checkType; |
| 2142 | 2144 | pub const valFullyResolved = types_resolved.checkVal; |
| 2143 | 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 | 2151 | pub const CoveragePoint = enum(u1) { |
| 2146 | 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 | 622 | .addrspace_cast, |
| 623 | 623 | .save_err_return_trace_index, |
| 624 | 624 | .vector_store_elem, |
| 625 | .tlv_dllimport_ptr, | |
| 625 | .runtime_nav_ptr, | |
| 626 | 626 | .c_va_arg, |
| 627 | 627 | .c_va_copy, |
| 628 | 628 | .c_va_end, |
src/Air/Liveness.zig+2-2| ... | ... | @@ -339,7 +339,7 @@ pub fn categorizeOperand( |
| 339 | 339 | .wasm_memory_size, |
| 340 | 340 | .err_return_trace, |
| 341 | 341 | .save_err_return_trace_index, |
| 342 | .tlv_dllimport_ptr, | |
| 342 | .runtime_nav_ptr, | |
| 343 | 343 | .c_va_start, |
| 344 | 344 | .work_item_id, |
| 345 | 345 | .work_group_size, |
| ... | ... | @@ -972,7 +972,7 @@ fn analyzeInst( |
| 972 | 972 | .wasm_memory_size, |
| 973 | 973 | .err_return_trace, |
| 974 | 974 | .save_err_return_trace_index, |
| 975 | .tlv_dllimport_ptr, | |
| 975 | .runtime_nav_ptr, | |
| 976 | 976 | .c_va_start, |
| 977 | 977 | .work_item_id, |
| 978 | 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 | 63 | .wasm_memory_size, |
| 64 | 64 | .err_return_trace, |
| 65 | 65 | .save_err_return_trace_index, |
| 66 | .tlv_dllimport_ptr, | |
| 66 | .runtime_nav_ptr, | |
| 67 | 67 | .c_va_start, |
| 68 | 68 | .work_item_id, |
| 69 | 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 | 321 | if (!checkRef(bin.rhs, zcu)) return false; |
| 322 | 322 | }, |
| 323 | 323 | |
| 324 | .tlv_dllimport_ptr => { | |
| 324 | .runtime_nav_ptr => { | |
| 325 | 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 | 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 | 353 | // Make a decision on whether to use LLVM backend for machine code generation. |
| 349 | 354 | // Note that using the LLVM backend does not necessarily mean using LLVM libraries. |
| 350 | 355 | // For example, Zig can emit .bc and .ll files directly, and this is still considered |
| 351 | 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 | 361 | // If emitting to LLVM bitcode object format, must use LLVM backend. |
| 354 | 362 | if (options.emit_llvm_ir or options.emit_llvm_bc) { |
| 355 | 363 | if (options.use_llvm == false) |
| ... | ... | @@ -382,9 +390,9 @@ pub fn resolve(options: Options) ResolveError!Config { |
| 382 | 390 | // Prefer LLVM for release builds. |
| 383 | 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 | |
| 386 | // https://github.com/ziglang/zig/issues/24046 | |
| 387 | if (pie) break :b true; | |
| 393 | // load_dynamic_library standalone test not passing on this combination | |
| 394 | // https://github.com/ziglang/zig/issues/24080 | |
| 395 | if (target.os.tag == .macos and is_dyn_lib) break :b true; | |
| 388 | 396 | |
| 389 | 397 | // At this point we would prefer to use our own self-hosted backend, |
| 390 | 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 | 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 | 403 | if (options.emit_bin and options.have_zcu) { |
| 403 | 404 | if (!use_lib_llvm and use_llvm) { |
| 404 | 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 | 436 | } |
| 436 | 437 | |
| 437 | 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 | 448 | const lto: std.zig.LtoMode = b: { |
src/InternPool.zig+71-49| ... | ... | @@ -526,10 +526,10 @@ pub const Nav = struct { |
| 526 | 526 | /// The type of this `Nav` is resolved; the value is queued for resolution. |
| 527 | 527 | type_resolved: struct { |
| 528 | 528 | type: InternPool.Index, |
| 529 | is_const: bool, | |
| 529 | 530 | alignment: Alignment, |
| 530 | 531 | @"linksection": OptionalNullTerminatedString, |
| 531 | 532 | @"addrspace": std.builtin.AddressSpace, |
| 532 | is_const: bool, | |
| 533 | 533 | is_threadlocal: bool, |
| 534 | 534 | /// This field is whether this `Nav` is a literal `extern` definition. |
| 535 | 535 | /// It does *not* tell you whether this might alias an extern fn (see #21027). |
| ... | ... | @@ -538,6 +538,7 @@ pub const Nav = struct { |
| 538 | 538 | /// The value of this `Nav` is resolved. |
| 539 | 539 | fully_resolved: struct { |
| 540 | 540 | val: InternPool.Index, |
| 541 | is_const: bool, | |
| 541 | 542 | alignment: Alignment, |
| 542 | 543 | @"linksection": OptionalNullTerminatedString, |
| 543 | 544 | @"addrspace": std.builtin.AddressSpace, |
| ... | ... | @@ -727,12 +728,12 @@ pub const Nav = struct { |
| 727 | 728 | const Bits = packed struct(u16) { |
| 728 | 729 | status: enum(u2) { unresolved, type_resolved, fully_resolved, type_resolved_extern_decl }, |
| 729 | 730 | /// Populated only if `bits.status != .unresolved`. |
| 731 | is_const: bool, | |
| 732 | /// Populated only if `bits.status != .unresolved`. | |
| 730 | 733 | alignment: Alignment, |
| 731 | 734 | /// Populated only if `bits.status != .unresolved`. |
| 732 | 735 | @"addrspace": std.builtin.AddressSpace, |
| 733 | 736 | /// Populated only if `bits.status == .type_resolved`. |
| 734 | is_const: bool, | |
| 735 | /// Populated only if `bits.status == .type_resolved`. | |
| 736 | 737 | is_threadlocal: bool, |
| 737 | 738 | is_usingnamespace: bool, |
| 738 | 739 | }; |
| ... | ... | @@ -753,15 +754,16 @@ pub const Nav = struct { |
| 753 | 754 | .unresolved => .unresolved, |
| 754 | 755 | .type_resolved, .type_resolved_extern_decl => .{ .type_resolved = .{ |
| 755 | 756 | .type = repr.type_or_val, |
| 757 | .is_const = repr.bits.is_const, | |
| 756 | 758 | .alignment = repr.bits.alignment, |
| 757 | 759 | .@"linksection" = repr.@"linksection", |
| 758 | 760 | .@"addrspace" = repr.bits.@"addrspace", |
| 759 | .is_const = repr.bits.is_const, | |
| 760 | 761 | .is_threadlocal = repr.bits.is_threadlocal, |
| 761 | 762 | .is_extern_decl = repr.bits.status == .type_resolved_extern_decl, |
| 762 | 763 | } }, |
| 763 | 764 | .fully_resolved => .{ .fully_resolved = .{ |
| 764 | 765 | .val = repr.type_or_val, |
| 766 | .is_const = repr.bits.is_const, | |
| 765 | 767 | .alignment = repr.bits.alignment, |
| 766 | 768 | .@"linksection" = repr.@"linksection", |
| 767 | 769 | .@"addrspace" = repr.bits.@"addrspace", |
| ... | ... | @@ -792,26 +794,26 @@ pub const Nav = struct { |
| 792 | 794 | .bits = switch (nav.status) { |
| 793 | 795 | .unresolved => .{ |
| 794 | 796 | .status = .unresolved, |
| 797 | .is_const = false, | |
| 795 | 798 | .alignment = .none, |
| 796 | 799 | .@"addrspace" = .generic, |
| 797 | 800 | .is_usingnamespace = nav.is_usingnamespace, |
| 798 | .is_const = false, | |
| 799 | 801 | .is_threadlocal = false, |
| 800 | 802 | }, |
| 801 | 803 | .type_resolved => |r| .{ |
| 802 | 804 | .status = if (r.is_extern_decl) .type_resolved_extern_decl else .type_resolved, |
| 805 | .is_const = r.is_const, | |
| 803 | 806 | .alignment = r.alignment, |
| 804 | 807 | .@"addrspace" = r.@"addrspace", |
| 805 | 808 | .is_usingnamespace = nav.is_usingnamespace, |
| 806 | .is_const = r.is_const, | |
| 807 | 809 | .is_threadlocal = r.is_threadlocal, |
| 808 | 810 | }, |
| 809 | 811 | .fully_resolved => |r| .{ |
| 810 | 812 | .status = .fully_resolved, |
| 813 | .is_const = r.is_const, | |
| 811 | 814 | .alignment = r.alignment, |
| 812 | 815 | .@"addrspace" = r.@"addrspace", |
| 813 | 816 | .is_usingnamespace = nav.is_usingnamespace, |
| 814 | .is_const = false, | |
| 815 | 817 | .is_threadlocal = false, |
| 816 | 818 | }, |
| 817 | 819 | }, |
| ... | ... | @@ -2221,7 +2223,6 @@ pub const Key = union(enum) { |
| 2221 | 2223 | init: Index, |
| 2222 | 2224 | owner_nav: Nav.Index, |
| 2223 | 2225 | is_threadlocal: bool, |
| 2224 | is_weak_linkage: bool, | |
| 2225 | 2226 | }; |
| 2226 | 2227 | |
| 2227 | 2228 | pub const Extern = struct { |
| ... | ... | @@ -2234,10 +2235,12 @@ pub const Key = union(enum) { |
| 2234 | 2235 | /// For example `extern "c" fn write(...) usize` would have 'c' as library name. |
| 2235 | 2236 | /// Index into the string table bytes. |
| 2236 | 2237 | lib_name: OptionalNullTerminatedString, |
| 2237 | is_const: bool, | |
| 2238 | linkage: std.builtin.GlobalLinkage, | |
| 2239 | visibility: std.builtin.SymbolVisibility, | |
| 2238 | 2240 | is_threadlocal: bool, |
| 2239 | is_weak_linkage: bool, | |
| 2240 | 2241 | is_dll_import: bool, |
| 2242 | relocation: std.builtin.ExternOptions.Relocation, | |
| 2243 | is_const: bool, | |
| 2241 | 2244 | alignment: Alignment, |
| 2242 | 2245 | @"addrspace": std.builtin.AddressSpace, |
| 2243 | 2246 | /// The ZIR instruction which created this extern; used only for source locations. |
| ... | ... | @@ -2844,9 +2847,10 @@ pub const Key = union(enum) { |
| 2844 | 2847 | |
| 2845 | 2848 | .@"extern" => |e| Hash.hash(seed, asBytes(&e.name) ++ |
| 2846 | 2849 | asBytes(&e.ty) ++ asBytes(&e.lib_name) ++ |
| 2847 | asBytes(&e.is_const) ++ asBytes(&e.is_threadlocal) ++ | |
| 2848 | asBytes(&e.is_weak_linkage) ++ asBytes(&e.alignment) ++ | |
| 2849 | asBytes(&e.is_dll_import) ++ asBytes(&e.@"addrspace") ++ | |
| 2850 | asBytes(&e.linkage) ++ asBytes(&e.visibility) ++ | |
| 2851 | asBytes(&e.is_threadlocal) ++ asBytes(&e.is_dll_import) ++ | |
| 2852 | asBytes(&e.relocation) ++ | |
| 2853 | asBytes(&e.is_const) ++ asBytes(&e.alignment) ++ asBytes(&e.@"addrspace") ++ | |
| 2850 | 2854 | asBytes(&e.zir_index)), |
| 2851 | 2855 | }; |
| 2852 | 2856 | } |
| ... | ... | @@ -2928,21 +2932,22 @@ pub const Key = union(enum) { |
| 2928 | 2932 | |
| 2929 | 2933 | .variable => |a_info| { |
| 2930 | 2934 | const b_info = b.variable; |
| 2931 | return a_info.owner_nav == b_info.owner_nav and | |
| 2932 | a_info.ty == b_info.ty and | |
| 2935 | return a_info.ty == b_info.ty and | |
| 2933 | 2936 | a_info.init == b_info.init and |
| 2934 | a_info.is_threadlocal == b_info.is_threadlocal and | |
| 2935 | a_info.is_weak_linkage == b_info.is_weak_linkage; | |
| 2937 | a_info.owner_nav == b_info.owner_nav and | |
| 2938 | a_info.is_threadlocal == b_info.is_threadlocal; | |
| 2936 | 2939 | }, |
| 2937 | 2940 | .@"extern" => |a_info| { |
| 2938 | 2941 | const b_info = b.@"extern"; |
| 2939 | 2942 | return a_info.name == b_info.name and |
| 2940 | 2943 | a_info.ty == b_info.ty and |
| 2941 | 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 | 2947 | a_info.is_threadlocal == b_info.is_threadlocal and |
| 2944 | a_info.is_weak_linkage == b_info.is_weak_linkage and | |
| 2945 | 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 | 2951 | a_info.alignment == b_info.alignment and |
| 2947 | 2952 | a_info.@"addrspace" == b_info.@"addrspace" and |
| 2948 | 2953 | a_info.zir_index == b_info.zir_index; |
| ... | ... | @@ -4889,6 +4894,7 @@ pub const Index = enum(u32) { |
| 4889 | 4894 | float_c_longdouble_f128: struct { data: *Float128 }, |
| 4890 | 4895 | float_comptime_float: struct { data: *Float128 }, |
| 4891 | 4896 | variable: struct { data: *Tag.Variable }, |
| 4897 | threadlocal_variable: struct { data: *Tag.Variable }, | |
| 4892 | 4898 | @"extern": struct { data: *Tag.Extern }, |
| 4893 | 4899 | func_decl: struct { |
| 4894 | 4900 | const @"data.analysis.inferred_error_set" = opaque {}; |
| ... | ... | @@ -5548,6 +5554,9 @@ pub const Tag = enum(u8) { |
| 5548 | 5554 | /// A global variable. |
| 5549 | 5555 | /// data is extra index to Variable. |
| 5550 | 5556 | variable, |
| 5557 | /// A global threadlocal variable. | |
| 5558 | /// data is extra index to Variable. | |
| 5559 | threadlocal_variable, | |
| 5551 | 5560 | /// An extern function or variable. |
| 5552 | 5561 | /// data is extra index to Extern. |
| 5553 | 5562 | /// Some parts of the key are stored in `owner_nav`. |
| ... | ... | @@ -5863,6 +5872,7 @@ pub const Tag = enum(u8) { |
| 5863 | 5872 | .float_c_longdouble_f128 = .{ .summary = .@"@as(c_longdouble, {.payload%value})", .payload = f128 }, |
| 5864 | 5873 | .float_comptime_float = .{ .summary = .@"{.payload%value}", .payload = f128 }, |
| 5865 | 5874 | .variable = .{ .summary = .@"{.payload.owner_nav.fqn%summary#\"}", .payload = Variable }, |
| 5875 | .threadlocal_variable = .{ .summary = .@"{.payload.owner_nav.fqn%summary#\"}", .payload = Variable }, | |
| 5866 | 5876 | .@"extern" = .{ .summary = .@"{.payload.owner_nav.fqn%summary#\"}", .payload = Extern }, |
| 5867 | 5877 | .func_decl = .{ |
| 5868 | 5878 | .summary = .@"{.payload.owner_nav.fqn%summary#\"}", |
| ... | ... | @@ -5913,24 +5923,24 @@ pub const Tag = enum(u8) { |
| 5913 | 5923 | /// May be `none`. |
| 5914 | 5924 | init: Index, |
| 5915 | 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 | 5928 | pub const Extern = struct { |
| 5928 | // name, alignment, addrspace come from `owner_nav`. | |
| 5929 | // name, is_const, alignment, addrspace come from `owner_nav`. | |
| 5929 | 5930 | ty: Index, |
| 5930 | 5931 | lib_name: OptionalNullTerminatedString, |
| 5931 | flags: Variable.Flags, | |
| 5932 | flags: Flags, | |
| 5932 | 5933 | owner_nav: Nav.Index, |
| 5933 | 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 | 5946 | /// Trailing: |
| ... | ... | @@ -7248,14 +7258,17 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { |
| 7248 | 7258 | .ty = .comptime_float_type, |
| 7249 | 7259 | .storage = .{ .f128 = extraData(unwrapped_index.getExtra(ip), Float128, data).get() }, |
| 7250 | 7260 | } }, |
| 7251 | .variable => { | |
| 7261 | .variable, .threadlocal_variable => { | |
| 7252 | 7262 | const extra = extraData(unwrapped_index.getExtra(ip), Tag.Variable, data); |
| 7253 | 7263 | return .{ .variable = .{ |
| 7254 | 7264 | .ty = extra.ty, |
| 7255 | 7265 | .init = extra.init, |
| 7256 | 7266 | .owner_nav = extra.owner_nav, |
| 7257 | .is_threadlocal = extra.flags.is_threadlocal, | |
| 7258 | .is_weak_linkage = extra.flags.is_weak_linkage, | |
| 7267 | .is_threadlocal = switch (item.tag) { | |
| 7268 | else => unreachable, | |
| 7269 | .variable => false, | |
| 7270 | .threadlocal_variable => true, | |
| 7271 | }, | |
| 7259 | 7272 | } }; |
| 7260 | 7273 | }, |
| 7261 | 7274 | .@"extern" => { |
| ... | ... | @@ -7265,10 +7278,12 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { |
| 7265 | 7278 | .name = nav.name, |
| 7266 | 7279 | .ty = extra.ty, |
| 7267 | 7280 | .lib_name = extra.lib_name, |
| 7268 | .is_const = extra.flags.is_const, | |
| 7281 | .linkage = extra.flags.linkage, | |
| 7282 | .visibility = extra.flags.visibility, | |
| 7269 | 7283 | .is_threadlocal = extra.flags.is_threadlocal, |
| 7270 | .is_weak_linkage = extra.flags.is_weak_linkage, | |
| 7271 | 7284 | .is_dll_import = extra.flags.is_dll_import, |
| 7285 | .relocation = extra.flags.relocation, | |
| 7286 | .is_const = nav.status.fully_resolved.is_const, | |
| 7272 | 7287 | .alignment = nav.status.fully_resolved.alignment, |
| 7273 | 7288 | .@"addrspace" = nav.status.fully_resolved.@"addrspace", |
| 7274 | 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 | 7910 | const has_init = variable.init != .none; |
| 7896 | 7911 | if (has_init) assert(variable.ty == ip.typeOf(variable.init)); |
| 7897 | 7912 | items.appendAssumeCapacity(.{ |
| 7898 | .tag = .variable, | |
| 7913 | .tag = switch (variable.is_threadlocal) { | |
| 7914 | false => .variable, | |
| 7915 | true => .threadlocal_variable, | |
| 7916 | }, | |
| 7899 | 7917 | .data = try addExtra(extra, Tag.Variable{ |
| 7900 | 7918 | .ty = variable.ty, |
| 7901 | 7919 | .init = variable.init, |
| 7902 | 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 | 9140 | .name = key.name, |
| 9129 | 9141 | .fqn = key.name, |
| 9130 | 9142 | .val = extern_index, |
| 9143 | .is_const = key.is_const, | |
| 9131 | 9144 | .alignment = key.alignment, |
| 9132 | 9145 | .@"linksection" = .none, |
| 9133 | 9146 | .@"addrspace" = key.@"addrspace", |
| ... | ... | @@ -9136,10 +9149,11 @@ pub fn getExtern( |
| 9136 | 9149 | .ty = key.ty, |
| 9137 | 9150 | .lib_name = key.lib_name, |
| 9138 | 9151 | .flags = .{ |
| 9139 | .is_const = key.is_const, | |
| 9152 | .linkage = key.linkage, | |
| 9153 | .visibility = key.visibility, | |
| 9140 | 9154 | .is_threadlocal = key.is_threadlocal, |
| 9141 | .is_weak_linkage = key.is_weak_linkage, | |
| 9142 | 9155 | .is_dll_import = key.is_dll_import, |
| 9156 | .relocation = key.relocation, | |
| 9143 | 9157 | }, |
| 9144 | 9158 | .zir_index = key.zir_index, |
| 9145 | 9159 | .owner_nav = owner_nav, |
| ... | ... | @@ -9714,6 +9728,7 @@ fn finishFuncInstance( |
| 9714 | 9728 | .name = nav_name, |
| 9715 | 9729 | .fqn = try ip.namespacePtr(fn_namespace).internFullyQualifiedName(ip, gpa, tid, nav_name), |
| 9716 | 9730 | .val = func_index, |
| 9731 | .is_const = fn_owner_nav.status.fully_resolved.is_const, | |
| 9717 | 9732 | .alignment = fn_owner_nav.status.fully_resolved.alignment, |
| 9718 | 9733 | .@"linksection" = fn_owner_nav.status.fully_resolved.@"linksection", |
| 9719 | 9734 | .@"addrspace" = fn_owner_nav.status.fully_resolved.@"addrspace", |
| ... | ... | @@ -10300,13 +10315,13 @@ fn addExtraAssumeCapacity(extra: Local.Extra.Mutable, item: anytype) u32 { |
| 10300 | 10315 | u32, |
| 10301 | 10316 | i32, |
| 10302 | 10317 | FuncAnalysis, |
| 10318 | Tag.Extern.Flags, | |
| 10303 | 10319 | Tag.TypePointer.Flags, |
| 10304 | 10320 | Tag.TypeFunction.Flags, |
| 10305 | 10321 | Tag.TypePointer.PackedOffset, |
| 10306 | 10322 | Tag.TypeUnion.Flags, |
| 10307 | 10323 | Tag.TypeStruct.Flags, |
| 10308 | 10324 | Tag.TypeStructPacked.Flags, |
| 10309 | Tag.Variable.Flags, | |
| 10310 | 10325 | => @bitCast(@field(item, field.name)), |
| 10311 | 10326 | |
| 10312 | 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 | 10376 | |
| 10362 | 10377 | u32, |
| 10363 | 10378 | i32, |
| 10379 | Tag.Extern.Flags, | |
| 10364 | 10380 | Tag.TypePointer.Flags, |
| 10365 | 10381 | Tag.TypeFunction.Flags, |
| 10366 | 10382 | Tag.TypePointer.PackedOffset, |
| 10367 | 10383 | Tag.TypeUnion.Flags, |
| 10368 | 10384 | Tag.TypeStruct.Flags, |
| 10369 | 10385 | Tag.TypeStructPacked.Flags, |
| 10370 | Tag.Variable.Flags, | |
| 10371 | 10386 | FuncAnalysis, |
| 10372 | 10387 | => @bitCast(extra_item), |
| 10373 | 10388 | |
| ... | ... | @@ -11162,7 +11177,7 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void { |
| 11162 | 11177 | .float_c_longdouble_f80 => @sizeOf(Float80), |
| 11163 | 11178 | .float_c_longdouble_f128 => @sizeOf(Float128), |
| 11164 | 11179 | .float_comptime_float => @sizeOf(Float128), |
| 11165 | .variable => @sizeOf(Tag.Variable), | |
| 11180 | .variable, .threadlocal_variable => @sizeOf(Tag.Variable), | |
| 11166 | 11181 | .@"extern" => @sizeOf(Tag.Extern), |
| 11167 | 11182 | .func_decl => @sizeOf(Tag.FuncDecl), |
| 11168 | 11183 | .func_instance => b: { |
| ... | ... | @@ -11282,6 +11297,7 @@ fn dumpAllFallible(ip: *const InternPool) anyerror!void { |
| 11282 | 11297 | .float_c_longdouble_f128, |
| 11283 | 11298 | .float_comptime_float, |
| 11284 | 11299 | .variable, |
| 11300 | .threadlocal_variable, | |
| 11285 | 11301 | .@"extern", |
| 11286 | 11302 | .func_decl, |
| 11287 | 11303 | .func_instance, |
| ... | ... | @@ -11414,6 +11430,7 @@ pub fn createNav( |
| 11414 | 11430 | name: NullTerminatedString, |
| 11415 | 11431 | fqn: NullTerminatedString, |
| 11416 | 11432 | val: InternPool.Index, |
| 11433 | is_const: bool, | |
| 11417 | 11434 | alignment: Alignment, |
| 11418 | 11435 | @"linksection": OptionalNullTerminatedString, |
| 11419 | 11436 | @"addrspace": std.builtin.AddressSpace, |
| ... | ... | @@ -11430,6 +11447,7 @@ pub fn createNav( |
| 11430 | 11447 | .analysis = null, |
| 11431 | 11448 | .status = .{ .fully_resolved = .{ |
| 11432 | 11449 | .val = opts.val, |
| 11450 | .is_const = opts.is_const, | |
| 11433 | 11451 | .alignment = opts.alignment, |
| 11434 | 11452 | .@"linksection" = opts.@"linksection", |
| 11435 | 11453 | .@"addrspace" = opts.@"addrspace", |
| ... | ... | @@ -11482,10 +11500,10 @@ pub fn resolveNavType( |
| 11482 | 11500 | nav: Nav.Index, |
| 11483 | 11501 | resolved: struct { |
| 11484 | 11502 | type: InternPool.Index, |
| 11503 | is_const: bool, | |
| 11485 | 11504 | alignment: Alignment, |
| 11486 | 11505 | @"linksection": OptionalNullTerminatedString, |
| 11487 | 11506 | @"addrspace": std.builtin.AddressSpace, |
| 11488 | is_const: bool, | |
| 11489 | 11507 | is_threadlocal: bool, |
| 11490 | 11508 | is_extern_decl: bool, |
| 11491 | 11509 | }, |
| ... | ... | @@ -11512,9 +11530,9 @@ pub fn resolveNavType( |
| 11512 | 11530 | |
| 11513 | 11531 | var bits = nav_bits[unwrapped.index]; |
| 11514 | 11532 | bits.status = if (resolved.is_extern_decl) .type_resolved_extern_decl else .type_resolved; |
| 11533 | bits.is_const = resolved.is_const; | |
| 11515 | 11534 | bits.alignment = resolved.alignment; |
| 11516 | 11535 | bits.@"addrspace" = resolved.@"addrspace"; |
| 11517 | bits.is_const = resolved.is_const; | |
| 11518 | 11536 | bits.is_threadlocal = resolved.is_threadlocal; |
| 11519 | 11537 | @atomicStore(Nav.Repr.Bits, &nav_bits[unwrapped.index], bits, .release); |
| 11520 | 11538 | } |
| ... | ... | @@ -11526,6 +11544,7 @@ pub fn resolveNavValue( |
| 11526 | 11544 | nav: Nav.Index, |
| 11527 | 11545 | resolved: struct { |
| 11528 | 11546 | val: InternPool.Index, |
| 11547 | is_const: bool, | |
| 11529 | 11548 | alignment: Alignment, |
| 11530 | 11549 | @"linksection": OptionalNullTerminatedString, |
| 11531 | 11550 | @"addrspace": std.builtin.AddressSpace, |
| ... | ... | @@ -11553,6 +11572,7 @@ pub fn resolveNavValue( |
| 11553 | 11572 | |
| 11554 | 11573 | var bits = nav_bits[unwrapped.index]; |
| 11555 | 11574 | bits.status = .fully_resolved; |
| 11575 | bits.is_const = resolved.is_const; | |
| 11556 | 11576 | bits.alignment = resolved.alignment; |
| 11557 | 11577 | bits.@"addrspace" = resolved.@"addrspace"; |
| 11558 | 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 | 12027 | .error_union_error, |
| 12008 | 12028 | .enum_tag, |
| 12009 | 12029 | .variable, |
| 12030 | .threadlocal_variable, | |
| 12010 | 12031 | .@"extern", |
| 12011 | 12032 | .func_decl, |
| 12012 | 12033 | .func_instance, |
| ... | ... | @@ -12391,6 +12412,7 @@ pub fn zigTypeTag(ip: *const InternPool, index: Index) std.builtin.TypeId { |
| 12391 | 12412 | .float_c_longdouble_f128, |
| 12392 | 12413 | .float_comptime_float, |
| 12393 | 12414 | .variable, |
| 12415 | .threadlocal_variable, | |
| 12394 | 12416 | .@"extern", |
| 12395 | 12417 | .func_decl, |
| 12396 | 12418 | .func_instance, |
src/Sema.zig+42-11| ... | ... | @@ -26089,10 +26089,12 @@ fn resolveExternOptions( |
| 26089 | 26089 | zir_ref: Zir.Inst.Ref, |
| 26090 | 26090 | ) CompileError!struct { |
| 26091 | 26091 | name: InternPool.NullTerminatedString, |
| 26092 | library_name: InternPool.OptionalNullTerminatedString = .none, | |
| 26093 | linkage: std.builtin.GlobalLinkage = .strong, | |
| 26094 | is_thread_local: bool = false, | |
| 26095 | is_dll_import: bool = false, | |
| 26092 | library_name: InternPool.OptionalNullTerminatedString, | |
| 26093 | linkage: std.builtin.GlobalLinkage, | |
| 26094 | visibility: std.builtin.SymbolVisibility, | |
| 26095 | is_thread_local: bool, | |
| 26096 | is_dll_import: bool, | |
| 26097 | relocation: std.builtin.ExternOptions.Relocation, | |
| 26096 | 26098 | } { |
| 26097 | 26099 | const pt = sema.pt; |
| 26098 | 26100 | const zcu = pt.zcu; |
| ... | ... | @@ -26105,8 +26107,10 @@ fn resolveExternOptions( |
| 26105 | 26107 | const name_src = block.src(.{ .init_field_name = src.offset.node_offset_builtin_call_arg.builtin_call_node }); |
| 26106 | 26108 | const library_src = block.src(.{ .init_field_library = src.offset.node_offset_builtin_call_arg.builtin_call_node }); |
| 26107 | 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 | 26111 | const thread_local_src = block.src(.{ .init_field_thread_local = src.offset.node_offset_builtin_call_arg.builtin_call_node }); |
| 26109 | 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 | 26115 | const name_ref = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, pt.tid, "name", .no_embedded_nulls), name_src); |
| 26112 | 26116 | const name = try sema.toConstString(block, name_src, name_ref, .{ .simple = .extern_options }); |
| ... | ... | @@ -26118,6 +26122,10 @@ fn resolveExternOptions( |
| 26118 | 26122 | const linkage_val = try sema.resolveConstDefinedValue(block, linkage_src, linkage_ref, .{ .simple = .extern_options }); |
| 26119 | 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 | 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 | 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 | 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 | 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 | 26148 | if (name.len == 0) { |
| 26137 | 26149 | return sema.fail(block, name_src, "extern symbol name cannot be empty", .{}); |
| 26138 | 26150 | } |
| ... | ... | @@ -26145,8 +26157,10 @@ fn resolveExternOptions( |
| 26145 | 26157 | .name = try ip.getOrPutString(gpa, pt.tid, name, .no_embedded_nulls), |
| 26146 | 26158 | .library_name = try ip.getOrPutStringOpt(gpa, pt.tid, library_name, .no_embedded_nulls), |
| 26147 | 26159 | .linkage = linkage, |
| 26160 | .visibility = visibility, | |
| 26148 | 26161 | .is_thread_local = is_thread_local_val.toBool(), |
| 26149 | 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 | 26192 | } |
| 26179 | 26193 | |
| 26180 | 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 | 26207 | // TODO: error for threadlocal functions, non-const functions, etc |
| 26183 | 26208 | |
| ... | ... | @@ -26190,10 +26215,12 @@ fn zirBuiltinExtern( |
| 26190 | 26215 | .name = options.name, |
| 26191 | 26216 | .ty = ptr_info.child, |
| 26192 | 26217 | .lib_name = options.library_name, |
| 26193 | .is_const = ptr_info.flags.is_const, | |
| 26218 | .linkage = options.linkage, | |
| 26219 | .visibility = options.visibility, | |
| 26194 | 26220 | .is_threadlocal = options.is_thread_local, |
| 26195 | .is_weak_linkage = options.linkage == .weak, | |
| 26196 | 26221 | .is_dll_import = options.is_dll_import, |
| 26222 | .relocation = options.relocation, | |
| 26223 | .is_const = ptr_info.flags.is_const, | |
| 26197 | 26224 | .alignment = ptr_info.flags.alignment, |
| 26198 | 26225 | .@"addrspace" = ptr_info.flags.address_space, |
| 26199 | 26226 | // This instruction is just for source locations. |
| ... | ... | @@ -31685,12 +31712,15 @@ fn analyzeNavRefInner(sema: *Sema, block: *Block, src: LazySrcLoc, orig_nav_inde |
| 31685 | 31712 | |
| 31686 | 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 | 31716 | .unresolved => unreachable, |
| 31690 | 31717 | // dllimports go straight to `fully_resolved`; the only option is threadlocal |
| 31691 | 31718 | .type_resolved => |r| r.is_threadlocal, |
| 31692 | 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 | 31724 | .variable => |v| v.is_threadlocal, |
| 31695 | 31725 | else => false, |
| 31696 | 31726 | }, |
| ... | ... | @@ -31699,7 +31729,7 @@ fn analyzeNavRefInner(sema: *Sema, block: *Block, src: LazySrcLoc, orig_nav_inde |
| 31699 | 31729 | const ty, const alignment, const @"addrspace", const is_const = switch (nav_status) { |
| 31700 | 31730 | .unresolved => unreachable, |
| 31701 | 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 | 31734 | const ptr_ty = try pt.ptrTypeSema(.{ |
| 31705 | 31735 | .child = ty, |
| ... | ... | @@ -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 | 31744 | // This pointer is runtime-known; we need to emit an AIR instruction to create it. |
| 31715 | 31745 | return block.addInst(.{ |
| 31716 | .tag = .tlv_dllimport_ptr, | |
| 31746 | .tag = .runtime_nav_ptr, | |
| 31717 | 31747 | .data = .{ .ty_nav = .{ |
| 31718 | 31748 | .ty = ptr_ty.toIntern(), |
| 31719 | 31749 | .nav = nav_index, |
| ... | ... | @@ -36432,6 +36462,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { |
| 36432 | 36462 | .float_c_longdouble_f128, |
| 36433 | 36463 | .float_comptime_float, |
| 36434 | 36464 | .variable, |
| 36465 | .threadlocal_variable, | |
| 36435 | 36466 | .@"extern", |
| 36436 | 36467 | .func_decl, |
| 36437 | 36468 | .func_instance, |
src/Zcu.zig+3-9| ... | ... | @@ -2047,6 +2047,7 @@ pub const SrcLoc = struct { |
| 2047 | 2047 | .init_field_library, |
| 2048 | 2048 | .init_field_thread_local, |
| 2049 | 2049 | .init_field_dll_import, |
| 2050 | .init_field_relocation, | |
| 2050 | 2051 | => |builtin_call_node| { |
| 2051 | 2052 | const wanted = switch (src_loc.lazy) { |
| 2052 | 2053 | .init_field_name => "name", |
| ... | ... | @@ -2059,6 +2060,7 @@ pub const SrcLoc = struct { |
| 2059 | 2060 | .init_field_library => "library", |
| 2060 | 2061 | .init_field_thread_local => "thread_local", |
| 2061 | 2062 | .init_field_dll_import => "dll_import", |
| 2063 | .init_field_relocation => "relocation", | |
| 2062 | 2064 | else => unreachable, |
| 2063 | 2065 | }; |
| 2064 | 2066 | const tree = try src_loc.file_scope.getTree(zcu); |
| ... | ... | @@ -2506,6 +2508,7 @@ pub const LazySrcLoc = struct { |
| 2506 | 2508 | init_field_library: Ast.Node.Offset, |
| 2507 | 2509 | init_field_thread_local: Ast.Node.Offset, |
| 2508 | 2510 | init_field_dll_import: Ast.Node.Offset, |
| 2511 | init_field_relocation: Ast.Node.Offset, | |
| 2509 | 2512 | /// The source location points to the value of an item in a specific |
| 2510 | 2513 | /// case of a `switch`. |
| 2511 | 2514 | switch_case_item: SwitchItem, |
| ... | ... | @@ -4562,15 +4565,6 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.builtin.CallingConvention) union(enu |
| 4562 | 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 | 4568 | pub const CodegenFailError = error{ |
| 4575 | 4569 | /// Indicates the error message has been already stored at `Zcu.failed_codegen`. |
| 4576 | 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 | 1153 | // First, we must resolve the declaration's type. To do this, we analyze the type body if available, |
| 1154 | 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 | 1157 | .@"comptime" => unreachable, // this is not a Nav |
| 1158 | .unnamed_test, .@"test", .decltest => assert(nav_ty.zigTypeTag(zcu) == .@"fn"), | |
| 1159 | .@"usingnamespace" => {}, | |
| 1160 | .@"const" => {}, | |
| 1161 | .@"var" => try sema.validateVarType( | |
| 1162 | &block, | |
| 1163 | if (zir_decl.type_body != null) ty_src else init_src, | |
| 1164 | nav_ty, | |
| 1165 | zir_decl.linkage == .@"extern", | |
| 1166 | ), | |
| 1167 | } | |
| 1158 | .unnamed_test, .@"test", .decltest => { | |
| 1159 | assert(nav_ty.zigTypeTag(zcu) == .@"fn"); | |
| 1160 | break :is_const true; | |
| 1161 | }, | |
| 1162 | .@"usingnamespace", .@"const" => true, | |
| 1163 | .@"var" => { | |
| 1164 | try sema.validateVarType( | |
| 1165 | &block, | |
| 1166 | if (zir_decl.type_body != null) ty_src else init_src, | |
| 1167 | nav_ty, | |
| 1168 | zir_decl.linkage == .@"extern", | |
| 1169 | ); | |
| 1170 | break :is_const false; | |
| 1171 | }, | |
| 1172 | }; | |
| 1168 | 1173 | |
| 1169 | 1174 | // Now that we know the type, we can evaluate the alignment, linksection, and addrspace, to determine |
| 1170 | 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 | 1200 | .init = final_val.?.toIntern(), |
| 1196 | 1201 | .owner_nav = nav_id, |
| 1197 | 1202 | .is_threadlocal = zir_decl.is_threadlocal, |
| 1198 | .is_weak_linkage = false, | |
| 1199 | 1203 | } })), |
| 1200 | 1204 | else => final_val.?, |
| 1201 | 1205 | }, |
| ... | ... | @@ -1212,10 +1216,12 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr |
| 1212 | 1216 | .name = old_nav.name, |
| 1213 | 1217 | .ty = nav_ty.toIntern(), |
| 1214 | 1218 | .lib_name = try ip.getOrPutStringOpt(gpa, pt.tid, lib_name, .no_embedded_nulls), |
| 1215 | .is_const = zir_decl.kind == .@"const", | |
| 1216 | 1219 | .is_threadlocal = zir_decl.is_threadlocal, |
| 1217 | .is_weak_linkage = false, | |
| 1220 | .linkage = .strong, | |
| 1221 | .visibility = .default, | |
| 1218 | 1222 | .is_dll_import = false, |
| 1223 | .relocation = .any, | |
| 1224 | .is_const = is_const, | |
| 1219 | 1225 | .alignment = modifiers.alignment, |
| 1220 | 1226 | .@"addrspace" = modifiers.@"addrspace", |
| 1221 | 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 | 1249 | } |
| 1244 | 1250 | ip.resolveNavValue(nav_id, .{ |
| 1245 | 1251 | .val = nav_val.toIntern(), |
| 1252 | .is_const = is_const, | |
| 1246 | 1253 | .alignment = .none, |
| 1247 | 1254 | .@"linksection" = .none, |
| 1248 | 1255 | .@"addrspace" = .generic, |
| ... | ... | @@ -1286,6 +1293,7 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr |
| 1286 | 1293 | |
| 1287 | 1294 | ip.resolveNavValue(nav_id, .{ |
| 1288 | 1295 | .val = nav_val.toIntern(), |
| 1296 | .is_const = is_const, | |
| 1289 | 1297 | .alignment = modifiers.alignment, |
| 1290 | 1298 | .@"linksection" = modifiers.@"linksection", |
| 1291 | 1299 | .@"addrspace" = modifiers.@"addrspace", |
| ... | ... | @@ -1515,8 +1523,6 @@ fn analyzeNavType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileEr |
| 1515 | 1523 | // the pointer modifiers, i.e. alignment, linksection, addrspace. |
| 1516 | 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 | 1526 | const is_const = switch (zir_decl.kind) { |
| 1521 | 1527 | .@"comptime" => unreachable, |
| 1522 | 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 | 1548 | r.alignment != modifiers.alignment or |
| 1543 | 1549 | r.@"linksection" != modifiers.@"linksection" or |
| 1544 | 1550 | r.@"addrspace" != modifiers.@"addrspace" or |
| 1545 | zcu.navValIsConst(r.val) != is_const or | |
| 1551 | r.is_const != is_const or | |
| 1546 | 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 | 1556 | |
| 1551 | 1557 | ip.resolveNavType(nav_id, .{ |
| 1552 | 1558 | .type = resolved_ty.toIntern(), |
| 1559 | .is_const = is_const, | |
| 1553 | 1560 | .alignment = modifiers.alignment, |
| 1554 | 1561 | .@"linksection" = modifiers.@"linksection", |
| 1555 | 1562 | .@"addrspace" = modifiers.@"addrspace", |
| 1556 | .is_const = is_const, | |
| 1557 | 1563 | .is_threadlocal = zir_decl.is_threadlocal, |
| 1558 | 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 | 1756 | |
| 1751 | 1757 | if (build_options.enable_debug_extensions and comp.verbose_air) { |
| 1752 | 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 | 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 | 3583 | .lib_name = e.lib_name, |
| 3578 | 3584 | .is_const = e.is_const, |
| 3579 | 3585 | .is_threadlocal = e.is_threadlocal, |
| 3580 | .is_weak_linkage = e.is_weak_linkage, | |
| 3586 | .linkage = e.linkage, | |
| 3587 | .visibility = e.visibility, | |
| 3581 | 3588 | .is_dll_import = e.is_dll_import, |
| 3589 | .relocation = e.relocation, | |
| 3582 | 3590 | .alignment = e.alignment, |
| 3583 | 3591 | .@"addrspace" = e.@"addrspace", |
| 3584 | 3592 | .zir_index = e.zir_index, |
| ... | ... | @@ -3954,7 +3962,7 @@ pub fn navPtrType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Allocator.Err |
| 3954 | 3962 | const ty, const alignment, const @"addrspace", const is_const = switch (ip.getNav(nav_id).status) { |
| 3955 | 3963 | .unresolved => unreachable, |
| 3956 | 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 | 3967 | return pt.ptrType(.{ |
| 3960 | 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 | 880 | .is_named_enum_value => return self.fail("TODO implement is_named_enum_value", .{}), |
| 881 | 881 | .error_set_has_value => return self.fail("TODO implement error_set_has_value", .{}), |
| 882 | 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 | 885 | .c_va_arg => return self.fail("TODO implement c_va_arg", .{}), |
| 886 | 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 | 869 | .is_named_enum_value => return self.fail("TODO implement is_named_enum_value", .{}), |
| 870 | 870 | .error_set_has_value => return self.fail("TODO implement error_set_has_value", .{}), |
| 871 | 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 | 874 | .c_va_arg => return self.fail("TODO implement c_va_arg", .{}), |
| 875 | 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 | 1041 | _: std.fmt.FormatOptions, |
| 1042 | 1042 | writer: anytype, |
| 1043 | 1043 | ) @TypeOf(writer).Error!void { |
| 1044 | @import("../../print_air.zig").dumpInst( | |
| 1045 | data.inst, | |
| 1046 | data.func.pt, | |
| 1047 | data.func.air, | |
| 1048 | data.func.liveness, | |
| 1049 | ); | |
| 1044 | data.func.air.dumpInst(data.inst, data.func.pt, data.func.liveness); | |
| 1050 | 1045 | } |
| 1051 | 1046 | fn fmtAir(func: *Func, inst: Air.Inst.Index) std.fmt.Formatter(formatAir) { |
| 1052 | 1047 | return .{ .data = .{ .func = func, .inst = inst } }; |
| ... | ... | @@ -1656,7 +1651,7 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void { |
| 1656 | 1651 | .wrap_errunion_payload => try func.airWrapErrUnionPayload(inst), |
| 1657 | 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 | 1656 | .add_optimized, |
| 1662 | 1657 | .sub_optimized, |
| ... | ... | @@ -3626,7 +3621,7 @@ fn airWrapErrUnionErr(func: *Func, inst: Air.Inst.Index) !void { |
| 3626 | 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 | 3625 | const zcu = func.pt.zcu; |
| 3631 | 3626 | const ip = &zcu.intern_pool; |
| 3632 | 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 | 3636 | break :sym sym; |
| 3642 | 3637 | } |
| 3643 | 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 | 3641 | const dest_mcv = try func.allocRegOrMem(ptr_ty, inst, true); |
| 3647 | 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 | 723 | .is_named_enum_value => @panic("TODO implement is_named_enum_value"), |
| 724 | 724 | .error_set_has_value => @panic("TODO implement error_set_has_value"), |
| 725 | 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 | 728 | .c_va_arg => return self.fail("TODO implement c_va_arg", .{}), |
| 729 | 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 | 2057 | .error_set_has_value => cg.airErrorSetHasValue(inst), |
| 2058 | 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 | 2062 | .assembly, |
| 2063 | 2063 | .is_err_ptr, |
| ... | ... | @@ -7616,7 +7616,7 @@ fn airFrameAddress(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 7616 | 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 | 7620 | const ty_nav = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_nav; |
| 7621 | 7621 | const mod = cg.pt.zcu.navFileScope(cg.owner_nav).mod.?; |
| 7622 | 7622 | if (mod.single_threaded) { |
src/arch/x86_64/CodeGen.zig+173-42| ... | ... | @@ -274,6 +274,12 @@ pub const MCValue = union(enum) { |
| 274 | 274 | load_symbol: bits.SymbolOffset, |
| 275 | 275 | /// The address of the memory location not-yet-allocated by the linker. |
| 276 | 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 | 283 | /// The value is in memory at a constant offset from the address in a register. |
| 278 | 284 | indirect: bits.RegisterOffset, |
| 279 | 285 | /// The value is in memory. |
| ... | ... | @@ -314,6 +320,7 @@ pub const MCValue = union(enum) { |
| 314 | 320 | .eflags, |
| 315 | 321 | .register_overflow, |
| 316 | 322 | .lea_symbol, |
| 323 | .lea_pcrel, | |
| 317 | 324 | .lea_direct, |
| 318 | 325 | .lea_got, |
| 319 | 326 | .lea_frame, |
| ... | ... | @@ -327,6 +334,7 @@ pub const MCValue = union(enum) { |
| 327 | 334 | .register_quadruple, |
| 328 | 335 | .memory, |
| 329 | 336 | .load_symbol, |
| 337 | .load_pcrel, | |
| 330 | 338 | .load_got, |
| 331 | 339 | .load_direct, |
| 332 | 340 | .indirect, |
| ... | ... | @@ -429,6 +437,7 @@ pub const MCValue = union(enum) { |
| 429 | 437 | .register_overflow, |
| 430 | 438 | .register_mask, |
| 431 | 439 | .lea_symbol, |
| 440 | .lea_pcrel, | |
| 432 | 441 | .lea_direct, |
| 433 | 442 | .lea_got, |
| 434 | 443 | .lea_frame, |
| ... | ... | @@ -445,6 +454,7 @@ pub const MCValue = union(enum) { |
| 445 | 454 | .load_got => |sym_index| .{ .lea_got = sym_index }, |
| 446 | 455 | .load_frame => |frame_addr| .{ .lea_frame = frame_addr }, |
| 447 | 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 | 476 | .load_got, |
| 467 | 477 | .load_frame, |
| 468 | 478 | .load_symbol, |
| 479 | .load_pcrel, | |
| 469 | 480 | .elementwise_args, |
| 470 | 481 | .reserved_frame, |
| 471 | 482 | .air_ref, |
| ... | ... | @@ -477,6 +488,7 @@ pub const MCValue = union(enum) { |
| 477 | 488 | .lea_got => |sym_index| .{ .load_got = sym_index }, |
| 478 | 489 | .lea_frame => |frame_addr| .{ .load_frame = frame_addr }, |
| 479 | 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 | 517 | .load_frame, |
| 506 | 518 | .load_symbol, |
| 507 | 519 | .lea_symbol, |
| 520 | .load_pcrel, | |
| 521 | .lea_pcrel, | |
| 508 | 522 | => switch (off) { |
| 509 | 523 | 0 => mcv, |
| 510 | 524 | else => unreachable, // not offsettable |
| ... | ... | @@ -543,6 +557,7 @@ pub const MCValue = union(enum) { |
| 543 | 557 | .elementwise_args, |
| 544 | 558 | .reserved_frame, |
| 545 | 559 | .lea_symbol, |
| 560 | .lea_pcrel, | |
| 546 | 561 | => unreachable, |
| 547 | 562 | .memory => |addr| if (std.math.cast(i32, @as(i64, @bitCast(addr)))) |small_addr| .{ |
| 548 | 563 | .base = .{ .reg = .ds }, |
| ... | ... | @@ -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 | 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 | 645 | }), |
| 619 | 646 | .load_symbol => |pl| try writer.print("[sym:{} + 0x{x}]", .{ pl.sym_index, pl.off }), |
| 620 | 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 | 650 | .indirect => |pl| try writer.print("[{s} + 0x{x}]", .{ @tagName(pl.reg), pl.off }), |
| 622 | 651 | .load_direct => |pl| try writer.print("[direct:{d}]", .{pl}), |
| 623 | 652 | .lea_direct => |pl| try writer.print("direct:{d}", .{pl}), |
| ... | ... | @@ -655,6 +684,8 @@ const InstTracking = struct { |
| 655 | 684 | .lea_frame, |
| 656 | 685 | .load_symbol, |
| 657 | 686 | .lea_symbol, |
| 687 | .load_pcrel, | |
| 688 | .lea_pcrel, | |
| 658 | 689 | => result, |
| 659 | 690 | .dead, |
| 660 | 691 | .elementwise_args, |
| ... | ... | @@ -755,6 +786,8 @@ const InstTracking = struct { |
| 755 | 786 | .lea_frame, |
| 756 | 787 | .load_symbol, |
| 757 | 788 | .lea_symbol, |
| 789 | .load_pcrel, | |
| 790 | .lea_pcrel, | |
| 758 | 791 | => assert(std.meta.eql(self.long, target.long)), |
| 759 | 792 | .dead, |
| 760 | 793 | .eflags, |
| ... | ... | @@ -1228,12 +1261,7 @@ fn formatAir( |
| 1228 | 1261 | _: std.fmt.FormatOptions, |
| 1229 | 1262 | writer: anytype, |
| 1230 | 1263 | ) @TypeOf(writer).Error!void { |
| 1231 | @import("../../print_air.zig").dumpInst( | |
| 1232 | data.inst, | |
| 1233 | data.self.pt, | |
| 1234 | data.self.air, | |
| 1235 | data.self.liveness, | |
| 1236 | ); | |
| 1264 | data.self.air.dumpInst(data.inst, data.self.pt, data.self.liveness); | |
| 1237 | 1265 | } |
| 1238 | 1266 | fn fmtAir(self: *CodeGen, inst: Air.Inst.Index) std.fmt.Formatter(formatAir) { |
| 1239 | 1267 | return .{ .data = .{ .self = self, .inst = inst } }; |
| ... | ... | @@ -163487,31 +163515,49 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 163487 | 163515 | }; |
| 163488 | 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 | 163519 | .elf, .macho => { |
| 163492 | 163520 | const ty_nav = air_datas[@intFromEnum(inst)].ty_nav; |
| 163493 | 163521 | |
| 163494 | 163522 | const nav = ip.getNav(ty_nav.nav); |
| 163495 | const tlv_sym_index = sym: { | |
| 163523 | const sym_index, const relocation = sym: { | |
| 163496 | 163524 | if (cg.bin_file.cast(.elf)) |elf_file| { |
| 163497 | 163525 | const zo = elf_file.zigObjectPtr().?; |
| 163498 | 163526 | if (nav.getExtern(ip)) |e| { |
| 163499 | 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; | |
| 163501 | break :sym sym; | |
| 163502 | } | |
| 163503 | break :sym try zo.getOrCreateMetadataForNav(zcu, ty_nav.nav); | |
| 163504 | } | |
| 163505 | if (cg.bin_file.cast(.macho)) |macho_file| { | |
| 163528 | linkage: switch (e.linkage) { | |
| 163529 | .internal => {}, | |
| 163530 | .strong => switch (e.visibility) { | |
| 163531 | .default => zo.symbol(sym).flags.is_extern_ptr = true, | |
| 163532 | .hidden, .protected => {}, | |
| 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 | 163543 | const zo = macho_file.getZigObject().?; |
| 163507 | 163544 | if (nav.getExtern(ip)) |e| { |
| 163508 | 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; | |
| 163510 | break :sym sym; | |
| 163511 | } | |
| 163512 | break :sym try zo.getOrCreateMetadataForNav(macho_file, ty_nav.nav); | |
| 163513 | } | |
| 163514 | unreachable; | |
| 163546 | linkage: switch (e.linkage) { | |
| 163547 | .internal => {}, | |
| 163548 | .strong => switch (e.visibility) { | |
| 163549 | .default => zo.symbols.items[sym].flags.is_extern_ptr = true, | |
| 163550 | .hidden, .protected => {}, | |
| 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 | 163563 | if (cg.mod.pic) { |
| ... | ... | @@ -163520,13 +163566,14 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 163520 | 163566 | try cg.spillRegisters(&.{.rax}); |
| 163521 | 163567 | } |
| 163522 | 163568 | |
| 163523 | var slot = try cg.tempInit(.usize, .{ .lea_symbol = .{ | |
| 163524 | .sym_index = tlv_sym_index, | |
| 163525 | } }); | |
| 163569 | var slot = try cg.tempInit(.usize, switch (relocation) { | |
| 163570 | .any => .{ .lea_symbol = .{ .sym_index = sym_index } }, | |
| 163571 | .pcrel => .{ .lea_pcrel = .{ .sym_index = sym_index } }, | |
| 163572 | }); | |
| 163526 | 163573 | while (try slot.toRegClass(true, .general_purpose, cg)) {} |
| 163527 | 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 | 163578 | .c_va_arg => try cg.airVaArg(inst), |
| 163532 | 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 | 169236 | .register, |
| 169190 | 169237 | .register_offset, |
| 169191 | 169238 | .lea_symbol, |
| 169239 | .lea_pcrel, | |
| 169192 | 169240 | .lea_direct, |
| 169193 | 169241 | .lea_got, |
| 169194 | 169242 | .lea_frame, |
| ... | ... | @@ -169196,6 +169244,7 @@ fn load(self: *CodeGen, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) InnerE |
| 169196 | 169244 | .memory, |
| 169197 | 169245 | .indirect, |
| 169198 | 169246 | .load_symbol, |
| 169247 | .load_pcrel, | |
| 169199 | 169248 | .load_direct, |
| 169200 | 169249 | .load_got, |
| 169201 | 169250 | .load_frame, |
| ... | ... | @@ -169407,6 +169456,7 @@ fn store( |
| 169407 | 169456 | .register, |
| 169408 | 169457 | .register_offset, |
| 169409 | 169458 | .lea_symbol, |
| 169459 | .lea_pcrel, | |
| 169410 | 169460 | .lea_direct, |
| 169411 | 169461 | .lea_got, |
| 169412 | 169462 | .lea_frame, |
| ... | ... | @@ -169414,6 +169464,7 @@ fn store( |
| 169414 | 169464 | .memory, |
| 169415 | 169465 | .indirect, |
| 169416 | 169466 | .load_symbol, |
| 169467 | .load_pcrel, | |
| 169417 | 169468 | .load_direct, |
| 169418 | 169469 | .load_got, |
| 169419 | 169470 | .load_frame, |
| ... | ... | @@ -169883,6 +169934,7 @@ fn genUnOpMir(self: *CodeGen, mir_tag: Mir.Inst.FixedTag, dst_ty: Type, dst_mcv: |
| 169883 | 169934 | .register_overflow, |
| 169884 | 169935 | .register_mask, |
| 169885 | 169936 | .lea_symbol, |
| 169937 | .lea_pcrel, | |
| 169886 | 169938 | .lea_direct, |
| 169887 | 169939 | .lea_got, |
| 169888 | 169940 | .lea_frame, |
| ... | ... | @@ -169892,7 +169944,7 @@ fn genUnOpMir(self: *CodeGen, mir_tag: Mir.Inst.FixedTag, dst_ty: Type, dst_mcv: |
| 169892 | 169944 | => unreachable, // unmodifiable destination |
| 169893 | 169945 | .register => |dst_reg| try self.asmRegister(mir_tag, registerAlias(dst_reg, abi_size)), |
| 169894 | 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 | 169948 | const addr_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp); |
| 169897 | 169949 | const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg); |
| 169898 | 169950 | defer self.register_manager.unlockReg(addr_reg_lock); |
| ... | ... | @@ -171552,6 +171604,8 @@ fn genBinOp( |
| 171552 | 171604 | .register_mask, |
| 171553 | 171605 | .load_symbol, |
| 171554 | 171606 | .lea_symbol, |
| 171607 | .load_pcrel, | |
| 171608 | .lea_pcrel, | |
| 171555 | 171609 | .load_direct, |
| 171556 | 171610 | .lea_direct, |
| 171557 | 171611 | .load_got, |
| ... | ... | @@ -172740,6 +172794,7 @@ fn genBinOpMir( |
| 172740 | 172794 | .lea_got, |
| 172741 | 172795 | .lea_frame, |
| 172742 | 172796 | .lea_symbol, |
| 172797 | .lea_pcrel, | |
| 172743 | 172798 | .elementwise_args, |
| 172744 | 172799 | .reserved_frame, |
| 172745 | 172800 | .air_ref, |
| ... | ... | @@ -172831,6 +172886,8 @@ fn genBinOpMir( |
| 172831 | 172886 | .indirect, |
| 172832 | 172887 | .load_symbol, |
| 172833 | 172888 | .lea_symbol, |
| 172889 | .load_pcrel, | |
| 172890 | .lea_pcrel, | |
| 172834 | 172891 | .load_direct, |
| 172835 | 172892 | .lea_direct, |
| 172836 | 172893 | .load_got, |
| ... | ... | @@ -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 | 172967 | const OpInfo = ?struct { addr_reg: Register, addr_lock: RegisterLock }; |
| 172911 | 172968 | const limb_abi_size: u32 = @min(abi_size, 8); |
| 172912 | 172969 | |
| ... | ... | @@ -172953,8 +173010,9 @@ fn genBinOpMir( |
| 172953 | 173010 | .load_frame, |
| 172954 | 173011 | .lea_frame, |
| 172955 | 173012 | .lea_symbol, |
| 173013 | .lea_pcrel, | |
| 172956 | 173014 | => null, |
| 172957 | .memory, .load_symbol, .load_got, .load_direct => src: { | |
| 173015 | .memory, .load_symbol, .load_pcrel, .load_got, .load_direct => src: { | |
| 172958 | 173016 | switch (resolved_src_mcv) { |
| 172959 | 173017 | .memory => |addr| if (std.math.cast(i32, @as(i64, @bitCast(addr))) != null and |
| 172960 | 173018 | std.math.cast(i32, @as(i64, @bitCast(addr)) + abi_size - limb_abi_size) != null) |
| ... | ... | @@ -173093,6 +173151,8 @@ fn genBinOpMir( |
| 173093 | 173151 | .indirect, |
| 173094 | 173152 | .load_symbol, |
| 173095 | 173153 | .lea_symbol, |
| 173154 | .load_pcrel, | |
| 173155 | .lea_pcrel, | |
| 173096 | 173156 | .load_direct, |
| 173097 | 173157 | .lea_direct, |
| 173098 | 173158 | .load_got, |
| ... | ... | @@ -173160,6 +173220,7 @@ fn genIntMulComplexOpMir(self: *CodeGen, dst_ty: Type, dst_mcv: MCValue, src_mcv |
| 173160 | 173220 | .register_overflow, |
| 173161 | 173221 | .register_mask, |
| 173162 | 173222 | .lea_symbol, |
| 173223 | .lea_pcrel, | |
| 173163 | 173224 | .lea_direct, |
| 173164 | 173225 | .lea_got, |
| 173165 | 173226 | .lea_frame, |
| ... | ... | @@ -173222,6 +173283,8 @@ fn genIntMulComplexOpMir(self: *CodeGen, dst_ty: Type, dst_mcv: MCValue, src_mcv |
| 173222 | 173283 | .eflags, |
| 173223 | 173284 | .load_symbol, |
| 173224 | 173285 | .lea_symbol, |
| 173286 | .load_pcrel, | |
| 173287 | .lea_pcrel, | |
| 173225 | 173288 | .load_direct, |
| 173226 | 173289 | .lea_direct, |
| 173227 | 173290 | .load_got, |
| ... | ... | @@ -173281,7 +173344,7 @@ fn genIntMulComplexOpMir(self: *CodeGen, dst_ty: Type, dst_mcv: MCValue, src_mcv |
| 173281 | 173344 | } |
| 173282 | 173345 | }, |
| 173283 | 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 | 173348 | const tmp_reg = try self.copyToTmpRegister(dst_ty, dst_mcv); |
| 173286 | 173349 | const tmp_mcv = MCValue{ .register = tmp_reg }; |
| 173287 | 173350 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| ... | ... | @@ -173450,7 +173513,8 @@ fn genLocalDebugInfo( |
| 173450 | 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 | 173518 | .base = .{ .reloc = sym_off.sym_index }, |
| 173455 | 173519 | .mod = .{ .rm = .{ |
| 173456 | 173520 | .size = .qword, |
| ... | ... | @@ -174108,12 +174172,13 @@ fn airCmp(self: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) !v |
| 174108 | 174172 | .lea_got, |
| 174109 | 174173 | .lea_frame, |
| 174110 | 174174 | .lea_symbol, |
| 174175 | .lea_pcrel, | |
| 174111 | 174176 | .elementwise_args, |
| 174112 | 174177 | .reserved_frame, |
| 174113 | 174178 | .air_ref, |
| 174114 | 174179 | => unreachable, |
| 174115 | 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 | 174182 | switch (resolved_dst_mcv) { |
| 174118 | 174183 | .memory => |addr| if (std.math.cast( |
| 174119 | 174184 | i32, |
| ... | ... | @@ -174122,7 +174187,7 @@ fn airCmp(self: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) !v |
| 174122 | 174187 | i32, |
| 174123 | 174188 | @as(i64, @bitCast(addr)) + abi_size - 8, |
| 174124 | 174189 | ) != null) break :dst null, |
| 174125 | .load_symbol, .load_got, .load_direct => {}, | |
| 174190 | .load_symbol, .load_pcrel, .load_got, .load_direct => {}, | |
| 174126 | 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 | 174225 | .register_mask, |
| 174161 | 174226 | .indirect, |
| 174162 | 174227 | .lea_symbol, |
| 174228 | .lea_pcrel, | |
| 174163 | 174229 | .lea_direct, |
| 174164 | 174230 | .lea_got, |
| 174165 | 174231 | .lea_frame, |
| ... | ... | @@ -174168,7 +174234,7 @@ fn airCmp(self: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) !v |
| 174168 | 174234 | .air_ref, |
| 174169 | 174235 | => unreachable, |
| 174170 | 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 | 174238 | switch (resolved_src_mcv) { |
| 174173 | 174239 | .memory => |addr| if (std.math.cast( |
| 174174 | 174240 | i32, |
| ... | ... | @@ -174177,7 +174243,7 @@ fn airCmp(self: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) !v |
| 174177 | 174243 | i32, |
| 174178 | 174244 | @as(i64, @bitCast(addr)) + abi_size - 8, |
| 174179 | 174245 | ) != null) break :src null, |
| 174180 | .load_symbol, .load_got, .load_direct => {}, | |
| 174246 | .load_symbol, .load_pcrel, .load_got, .load_direct => {}, | |
| 174181 | 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 | 174634 | .lea_direct, |
| 174569 | 174635 | .lea_got, |
| 174570 | 174636 | .lea_symbol, |
| 174637 | .lea_pcrel, | |
| 174571 | 174638 | .elementwise_args, |
| 174572 | 174639 | .reserved_frame, |
| 174573 | 174640 | .air_ref, |
| ... | ... | @@ -174616,6 +174683,7 @@ fn isNull(self: *CodeGen, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) |
| 174616 | 174683 | |
| 174617 | 174684 | .memory, |
| 174618 | 174685 | .load_symbol, |
| 174686 | .load_pcrel, | |
| 174619 | 174687 | .load_got, |
| 174620 | 174688 | .load_direct, |
| 174621 | 174689 | => { |
| ... | ... | @@ -176625,6 +176693,7 @@ fn genCopy(self: *CodeGen, ty: Type, dst_mcv: MCValue, src_mcv: MCValue, opts: C |
| 176625 | 176693 | .lea_got, |
| 176626 | 176694 | .lea_frame, |
| 176627 | 176695 | .lea_symbol, |
| 176696 | .lea_pcrel, | |
| 176628 | 176697 | .elementwise_args, |
| 176629 | 176698 | .reserved_frame, |
| 176630 | 176699 | .air_ref, |
| ... | ... | @@ -176719,7 +176788,7 @@ fn genCopy(self: *CodeGen, ty: Type, dst_mcv: MCValue, src_mcv: MCValue, opts: C |
| 176719 | 176788 | } |
| 176720 | 176789 | return; |
| 176721 | 176790 | }, |
| 176722 | .load_symbol, .load_direct, .load_got => { | |
| 176791 | .load_symbol, .load_pcrel, .load_direct, .load_got => { | |
| 176723 | 176792 | const src_addr_reg = |
| 176724 | 176793 | (try self.register_manager.allocReg(null, abi.RegisterClass.gp)).to64(); |
| 176725 | 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 | 176821 | .undef => if (opts.safety and part_i > 0) .{ .register = dst_regs[0] } else .undef, |
| 176753 | 176822 | dst_tag => |src_regs| .{ .register = src_regs[part_i] }, |
| 176754 | 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 | 176825 | .reg = src_info.?.addr_reg, |
| 176757 | 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 | 176842 | src_mcv, |
| 176774 | 176843 | opts, |
| 176775 | 176844 | ), |
| 176776 | .memory, .load_symbol, .load_direct, .load_got => { | |
| 176845 | .memory, .load_symbol, .load_pcrel, .load_direct, .load_got => { | |
| 176777 | 176846 | switch (dst_mcv) { |
| 176778 | 176847 | .memory => |addr| if (std.math.cast(i32, @as(i64, @bitCast(addr)))) |small_addr| |
| 176779 | 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 | 176850 | else => unreachable, |
| 176782 | 176851 | } |
| 176783 | 176852 | |
| ... | ... | @@ -177234,7 +177303,7 @@ fn genSetReg( |
| 177234 | 177303 | if (src_reg_mask.info.inverted) try self.asmRegister(.{ ._, .not }, registerAlias(bits_reg, abi_size)); |
| 177235 | 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 | 177307 | switch (src_mcv) { |
| 177239 | 177308 | .memory => |addr| if (std.math.cast(i32, @as(i64, @bitCast(addr)))) |small_addr| |
| 177240 | 177309 | return (try self.moveStrategy( |
| ... | ... | @@ -177263,6 +177332,21 @@ fn genSetReg( |
| 177263 | 177332 | .segment, .mmx, .ip, .cr, .dr => unreachable, |
| 177264 | 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 | 177350 | .load_direct => |sym_index| switch (dst_reg.class()) { |
| 177267 | 177351 | .general_purpose, .gphi => { |
| 177268 | 177352 | _ = try self.addInst(.{ |
| ... | ... | @@ -177313,6 +177397,28 @@ fn genSetReg( |
| 177313 | 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 | 177422 | .lea_direct, .lea_got => |sym_index| _ = try self.addInst(.{ |
| 177317 | 177423 | .tag = switch (src_mcv) { |
| 177318 | 177424 | .lea_direct => .lea, |
| ... | ... | @@ -177350,6 +177456,7 @@ fn genSetMem( |
| 177350 | 177456 | .frame => |base_frame_index| .{ .lea_frame = .{ .index = base_frame_index, .off = disp } }, |
| 177351 | 177457 | .table, .rip_inst => unreachable, |
| 177352 | 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 | 177461 | switch (src_mcv) { |
| 177355 | 177462 | .none, |
| ... | ... | @@ -177466,7 +177573,7 @@ fn genSetMem( |
| 177466 | 177573 | .off = disp, |
| 177467 | 177574 | }).compare(.gte, src_align), |
| 177468 | 177575 | .table, .rip_inst => unreachable, |
| 177469 | .reloc => false, | |
| 177576 | .reloc, .pcrel => false, | |
| 177470 | 177577 | })).write( |
| 177471 | 177578 | self, |
| 177472 | 177579 | .{ .base = base, .mod = .{ .rm = .{ |
| ... | ... | @@ -177557,6 +177664,8 @@ fn genSetMem( |
| 177557 | 177664 | .lea_frame, |
| 177558 | 177665 | .load_symbol, |
| 177559 | 177666 | .lea_symbol, |
| 177667 | .load_pcrel, | |
| 177668 | .lea_pcrel, | |
| 177560 | 177669 | => switch (abi_size) { |
| 177561 | 177670 | 0 => {}, |
| 177562 | 177671 | 1, 2, 4, 8 => { |
| ... | ... | @@ -178110,7 +178219,7 @@ fn airCmpxchg(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 178110 | 178219 | .off => return self.fail("TODO airCmpxchg with {s}", .{@tagName(ptr_mcv)}), |
| 178111 | 178220 | } |
| 178112 | 178221 | const ptr_lock = switch (ptr_mem.base) { |
| 178113 | .none, .frame, .reloc => null, | |
| 178222 | .none, .frame, .reloc, .pcrel => null, | |
| 178114 | 178223 | .reg => |reg| self.register_manager.lockReg(reg), |
| 178115 | 178224 | .table, .rip_inst => unreachable, |
| 178116 | 178225 | }; |
| ... | ... | @@ -178193,7 +178302,7 @@ fn atomicOp( |
| 178193 | 178302 | .off => return self.fail("TODO airCmpxchg with {s}", .{@tagName(ptr_mcv)}), |
| 178194 | 178303 | } |
| 178195 | 178304 | const mem_lock = switch (ptr_mem.base) { |
| 178196 | .none, .frame, .reloc => null, | |
| 178305 | .none, .frame, .reloc, .pcrel => null, | |
| 178197 | 178306 | .reg => |reg| self.register_manager.lockReg(reg), |
| 178198 | 178307 | .table, .rip_inst => unreachable, |
| 178199 | 178308 | }; |
| ... | ... | @@ -182266,6 +182375,8 @@ const Temp = struct { |
| 182266 | 182375 | .memory, |
| 182267 | 182376 | .load_symbol, |
| 182268 | 182377 | .lea_symbol, |
| 182378 | .load_pcrel, | |
| 182379 | .lea_pcrel, | |
| 182269 | 182380 | .indirect, |
| 182270 | 182381 | .load_direct, |
| 182271 | 182382 | .lea_direct, |
| ... | ... | @@ -182427,6 +182538,22 @@ const Temp = struct { |
| 182427 | 182538 | assert(limb_index == 0); |
| 182428 | 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 | 182557 | .load_frame => |frame_addr| { |
| 182431 | 182558 | const new_reg = |
| 182432 | 182559 | try cg.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp); |
| ... | ... | @@ -182721,11 +182848,12 @@ const Temp = struct { |
| 182721 | 182848 | .memory, |
| 182722 | 182849 | .indirect, |
| 182723 | 182850 | .load_symbol, |
| 182851 | .load_pcrel, | |
| 182724 | 182852 | .load_direct, |
| 182725 | 182853 | .load_got, |
| 182726 | 182854 | .load_frame, |
| 182727 | 182855 | => return temp.toRegClass(true, .general_purpose, cg), |
| 182728 | .lea_symbol => |sym_off| { | |
| 182856 | .lea_symbol, .lea_pcrel => |sym_off| { | |
| 182729 | 182857 | const off = sym_off.off; |
| 182730 | 182858 | // hack around linker relocation bugs |
| 182731 | 182859 | if (false and off == 0) return false; |
| ... | ... | @@ -187464,6 +187592,8 @@ const Temp = struct { |
| 187464 | 187592 | .memory, |
| 187465 | 187593 | .load_symbol, |
| 187466 | 187594 | .lea_symbol, |
| 187595 | .load_pcrel, | |
| 187596 | .lea_pcrel, | |
| 187467 | 187597 | .indirect, |
| 187468 | 187598 | .load_direct, |
| 187469 | 187599 | .lea_direct, |
| ... | ... | @@ -190044,6 +190174,7 @@ const Select = struct { |
| 190044 | 190174 | .register => |base_reg| .{ .reg = base_reg.toSize(.ptr, s.cg.target) }, |
| 190045 | 190175 | .register_offset => |base_reg_off| .{ .reg = base_reg_off.reg.toSize(.ptr, s.cg.target) }, |
| 190046 | 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 | 190179 | .mod = .{ .rm = .{ |
| 190049 | 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 | 189 | .r_addend = lowered_relocs[0].off, |
| 190 | 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 | 193 | const zo = elf_file.zigObjectPtr().?; |
| 194 | 194 | const atom = zo.symbol(emit.atom_index).atom(elf_file).?; |
| 195 | 195 | const sym = zo.symbol(sym_index); |
| 196 | 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 | 198 | @intFromEnum(std.elf.R_X86_64.GOTPCREL) |
| 199 | 199 | else |
| 200 | 200 | @intFromEnum(std.elf.R_X86_64.PC32); |
| ... | ... | @@ -218,7 +218,7 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 218 | 218 | const zo = macho_file.getZigObject().?; |
| 219 | 219 | const atom = zo.symbols.items[emit.atom_index].getAtom(macho_file).?; |
| 220 | 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 | 222 | .got_load |
| 223 | 223 | else if (sym.flags.tlv) |
| 224 | 224 | .tlv |
| ... | ... | @@ -438,6 +438,7 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 438 | 438 | .reg => |reg| .{ .breg = reg.dwarfNum() }, |
| 439 | 439 | .frame, .table, .rip_inst => unreachable, |
| 440 | 440 | .reloc => |sym_index| .{ .addr_reloc = sym_index }, |
| 441 | .pcrel => unreachable, | |
| 441 | 442 | }; |
| 442 | 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 | 66 | inst: Mir.Inst.Index, |
| 67 | 67 | table, |
| 68 | 68 | linker_reloc: u32, |
| 69 | linker_pcrel: u32, | |
| 69 | 70 | linker_tlsld: u32, |
| 70 | 71 | linker_dtpoff: u32, |
| 71 | 72 | linker_extern_fn: u32, |
| ... | ... | @@ -421,9 +422,9 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand) |
| 421 | 422 | for (emit_ops, ops, 0..) |*emit_op, op, op_index| { |
| 422 | 423 | emit_op.* = switch (op) { |
| 423 | 424 | else => op, |
| 424 | .mem => |mem_op| switch (mem_op.base()) { | |
| 425 | .mem => |mem_op| op: switch (mem_op.base()) { | |
| 425 | 426 | else => op, |
| 426 | .reloc => |sym_index| op: { | |
| 427 | .reloc => |sym_index| { | |
| 427 | 428 | assert(prefix == .none); |
| 428 | 429 | assert(mem_op.sib.disp == 0); |
| 429 | 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 | 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 | 1866 | .none, .table => undefined, |
| 1867 | 1867 | .reg => |reg| @intFromEnum(reg), |
| 1868 | 1868 | .frame => |frame_index| @intFromEnum(frame_index), |
| 1869 | .reloc => |sym_index| sym_index, | |
| 1869 | .reloc, .pcrel => |sym_index| sym_index, | |
| 1870 | 1870 | .rip_inst => |inst_index| inst_index, |
| 1871 | 1871 | }, |
| 1872 | 1872 | .off = switch (mem.mod) { |
| ... | ... | @@ -1895,6 +1895,7 @@ pub const Memory = struct { |
| 1895 | 1895 | .frame => .{ .frame = @enumFromInt(mem.base) }, |
| 1896 | 1896 | .table => .table, |
| 1897 | 1897 | .reloc => .{ .reloc = mem.base }, |
| 1898 | .pcrel => .{ .pcrel = mem.base }, | |
| 1898 | 1899 | .rip_inst => .{ .rip_inst = mem.base }, |
| 1899 | 1900 | }, |
| 1900 | 1901 | .scale_index = switch (mem.info.index) { |
| ... | ... | @@ -1959,7 +1960,7 @@ pub fn resolveFrameAddr(mir: Mir, frame_addr: bits.FrameAddr) bits.RegisterOffse |
| 1959 | 1960 | |
| 1960 | 1961 | pub fn resolveFrameLoc(mir: Mir, mem: Memory) Memory { |
| 1961 | 1962 | return switch (mem.info.base) { |
| 1962 | .none, .reg, .table, .reloc, .rip_inst => mem, | |
| 1963 | .none, .reg, .table, .reloc, .pcrel, .rip_inst => mem, | |
| 1963 | 1964 | .frame => if (mir.frame_locs.len > 0) .{ |
| 1964 | 1965 | .info = .{ |
| 1965 | 1966 | .base = .reg, |
src/arch/x86_64/bits.zig+1| ... | ... | @@ -762,6 +762,7 @@ pub const Memory = struct { |
| 762 | 762 | frame: FrameIndex, |
| 763 | 763 | table, |
| 764 | 764 | reloc: u32, |
| 765 | pcrel: u32, | |
| 765 | 766 | rip_inst: Mir.Inst.Index, |
| 766 | 767 | |
| 767 | 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 | 138 | .moffs => true, |
| 139 | 139 | .rip => false, |
| 140 | 140 | .sib => |s| switch (s.base) { |
| 141 | .none, .frame, .table, .reloc, .rip_inst => false, | |
| 141 | .none, .frame, .table, .reloc, .pcrel, .rip_inst => false, | |
| 142 | 142 | .reg => |reg| reg.isClass(.segment), |
| 143 | 143 | }, |
| 144 | 144 | }; |
| ... | ... | @@ -211,7 +211,7 @@ pub const Instruction = struct { |
| 211 | 211 | .none, .imm => 0b00, |
| 212 | 212 | .reg => |reg| @truncate(reg.enc() >> 3), |
| 213 | 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 | 215 | .reg => |reg| @truncate(reg.enc() >> 3), |
| 216 | 216 | }, |
| 217 | 217 | .bytes => unreachable, |
| ... | ... | @@ -282,6 +282,7 @@ pub const Instruction = struct { |
| 282 | 282 | .frame => |frame_index| try writer.print("{}", .{frame_index}), |
| 283 | 283 | .table => try writer.print("Table", .{}), |
| 284 | 284 | .reloc => |sym_index| try writer.print("Symbol({d})", .{sym_index}), |
| 285 | .pcrel => |sym_index| try writer.print("PcRelSymbol({d})", .{sym_index}), | |
| 285 | 286 | .rip_inst => |inst_index| try writer.print("RipInst({d})", .{inst_index}), |
| 286 | 287 | } |
| 287 | 288 | if (mem.scaleIndex()) |si| { |
| ... | ... | @@ -721,7 +722,7 @@ pub const Instruction = struct { |
| 721 | 722 | try encoder.modRm_indirectDisp32(operand_enc, 0); |
| 722 | 723 | try encoder.disp32(undefined); |
| 723 | 724 | } else return error.CannotEncode, |
| 724 | .rip_inst => { | |
| 725 | .pcrel, .rip_inst => { | |
| 725 | 726 | try encoder.modRm_RIPDisp32(operand_enc); |
| 726 | 727 | try encoder.disp32(sib.disp); |
| 727 | 728 | }, |
src/codegen.zig+57-24| ... | ... | @@ -921,41 +921,74 @@ fn genNavRef( |
| 921 | 921 | const nav = ip.getNav(nav_index); |
| 922 | 922 | assert(!nav.isThreadlocal(ip)); |
| 923 | 923 | |
| 924 | const is_extern, const lib_name = if (nav.getExtern(ip)) |e| | |
| 925 | .{ true, e.lib_name } | |
| 924 | const lib_name, const linkage, const visibility = if (nav.getExtern(ip)) |e| | |
| 925 | .{ e.lib_name, e.linkage, e.visibility } | |
| 926 | 926 | else |
| 927 | .{ false, .none }; | |
| 927 | .{ .none, .internal, .default }; | |
| 928 | 928 | |
| 929 | 929 | const name = nav.name; |
| 930 | 930 | if (lf.cast(.elf)) |elf_file| { |
| 931 | 931 | const zo = elf_file.zigObjectPtr().?; |
| 932 | if (is_extern) { | |
| 933 | const sym_index = try elf_file.getGlobalSymbol(name.toSlice(ip), lib_name.toSlice(ip)); | |
| 934 | zo.symbol(sym_index).flags.is_extern_ptr = true; | |
| 935 | return .{ .mcv = .{ .lea_symbol = sym_index } }; | |
| 932 | switch (linkage) { | |
| 933 | .internal => { | |
| 934 | const sym_index = try zo.getOrCreateMetadataForNav(zcu, nav_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 | 953 | } else if (lf.cast(.macho)) |macho_file| { |
| 940 | 954 | const zo = macho_file.getZigObject().?; |
| 941 | if (is_extern) { | |
| 942 | const sym_index = try macho_file.getGlobalSymbol(name.toSlice(ip), lib_name.toSlice(ip)); | |
| 943 | zo.symbols.items[sym_index].flags.is_extern_ptr = true; | |
| 944 | return .{ .mcv = .{ .lea_symbol = sym_index } }; | |
| 955 | switch (linkage) { | |
| 956 | .internal => { | |
| 957 | const sym_index = try zo.getOrCreateMetadataForNav(macho_file, nav_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 | 977 | } else if (lf.cast(.coff)) |coff_file| { |
| 950 | if (is_extern) { | |
| 951 | // TODO audit this | |
| 952 | const global_index = try coff_file.getGlobalSymbol(name.toSlice(ip), lib_name.toSlice(ip)); | |
| 953 | try coff_file.need_got_table.put(gpa, global_index, {}); // needs GOT | |
| 954 | return .{ .mcv = .{ .load_got = link.File.Coff.global_symbol_bit | global_index } }; | |
| 978 | // TODO audit this | |
| 979 | switch (linkage) { | |
| 980 | .internal => { | |
| 981 | const atom_index = try coff_file.getOrCreateAtomForNav(nav_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 | 992 | } else if (lf.cast(.plan9)) |p9| { |
| 960 | 993 | const atom_index = try p9.seeNav(pt, nav_index); |
| 961 | 994 | const atom = p9.getAtom(atom_index); |
src/codegen/c.zig+22-12| ... | ... | @@ -2255,19 +2255,30 @@ pub const DeclGen = struct { |
| 2255 | 2255 | fn renderFwdDecl( |
| 2256 | 2256 | dg: *DeclGen, |
| 2257 | 2257 | nav_index: InternPool.Nav.Index, |
| 2258 | flags: struct { | |
| 2259 | is_extern: bool, | |
| 2258 | flags: packed struct { | |
| 2260 | 2259 | is_const: bool, |
| 2261 | 2260 | is_threadlocal: bool, |
| 2262 | is_weak_linkage: bool, | |
| 2261 | linkage: std.builtin.GlobalLinkage, | |
| 2262 | visibility: std.builtin.SymbolVisibility, | |
| 2263 | 2263 | }, |
| 2264 | 2264 | ) !void { |
| 2265 | 2265 | const zcu = dg.pt.zcu; |
| 2266 | 2266 | const ip = &zcu.intern_pool; |
| 2267 | 2267 | const nav = ip.getNav(nav_index); |
| 2268 | 2268 | const fwd = dg.fwdDeclWriter(); |
| 2269 | try fwd.writeAll(if (flags.is_extern) "zig_extern " else "static "); | |
| 2270 | if (flags.is_weak_linkage) try fwd.writeAll("zig_weak_linkage "); | |
| 2269 | try fwd.writeAll(switch (flags.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 | 2282 | if (flags.is_threadlocal and !dg.mod.single_threaded) try fwd.writeAll("zig_threadlocal "); |
| 2272 | 2283 | try dg.renderTypeAndName( |
| 2273 | 2284 | fwd, |
| ... | ... | @@ -2994,10 +3005,10 @@ pub fn genDecl(o: *Object) !void { |
| 2994 | 3005 | switch (ip.indexToKey(nav.status.fully_resolved.val)) { |
| 2995 | 3006 | .@"extern" => |@"extern"| { |
| 2996 | 3007 | if (!ip.isFunctionType(nav_ty.toIntern())) return o.dg.renderFwdDecl(o.dg.pass.nav, .{ |
| 2997 | .is_extern = true, | |
| 2998 | 3008 | .is_const = @"extern".is_const, |
| 2999 | 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 | 3014 | const fwd = o.dg.fwdDeclWriter(); |
| ... | ... | @@ -3016,13 +3027,12 @@ pub fn genDecl(o: *Object) !void { |
| 3016 | 3027 | }, |
| 3017 | 3028 | .variable => |variable| { |
| 3018 | 3029 | try o.dg.renderFwdDecl(o.dg.pass.nav, .{ |
| 3019 | .is_extern = false, | |
| 3020 | 3030 | .is_const = false, |
| 3021 | 3031 | .is_threadlocal = variable.is_threadlocal, |
| 3022 | .is_weak_linkage = variable.is_weak_linkage, | |
| 3032 | .linkage = .internal, | |
| 3033 | .visibility = .default, | |
| 3023 | 3034 | }); |
| 3024 | 3035 | const w = o.writer(); |
| 3025 | if (variable.is_weak_linkage) try w.writeAll("zig_weak_linkage "); | |
| 3026 | 3036 | if (variable.is_threadlocal and !o.dg.mod.single_threaded) try w.writeAll("zig_threadlocal "); |
| 3027 | 3037 | if (nav.status.fully_resolved.@"linksection".toSlice(&zcu.intern_pool)) |s| |
| 3028 | 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 | 3477 | .error_set_has_value => return f.fail("TODO: C backend: implement error_set_has_value", .{}), |
| 3468 | 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 | 3482 | .c_va_start => try airCVaStart(f, inst), |
| 3473 | 3483 | .c_va_arg => try airCVaArg(f, inst), |
| ... | ... | @@ -7672,7 +7682,7 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7672 | 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 | 7686 | const ty_nav = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_nav; |
| 7677 | 7687 | const writer = f.object.writer(); |
| 7678 | 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 | 2979 | const zcu = pt.zcu; |
| 2980 | 2980 | const ip = &zcu.intern_pool; |
| 2981 | 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 | 2983 | .unresolved => unreachable, |
| 2984 | 2984 | .fully_resolved => |r| switch (ip.indexToKey(r.val)) { |
| 2985 | .variable => |variable| .{ false, variable.is_threadlocal, variable.is_weak_linkage, false }, | |
| 2986 | .@"extern" => |@"extern"| .{ true, @"extern".is_threadlocal, @"extern".is_weak_linkage, @"extern".is_dll_import }, | |
| 2987 | else => .{ false, false, false, false }, | |
| 2985 | .variable => |variable| .{ .internal, .default, variable.is_threadlocal, false }, | |
| 2986 | .@"extern" => |@"extern"| .{ @"extern".linkage, .fromSymbolVisibility(@"extern".visibility), @"extern".is_threadlocal, @"extern".is_dll_import }, | |
| 2987 | else => .{ .internal, .default, false, false }, | |
| 2988 | 2988 | }, |
| 2989 | 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 | 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 | 2999 | try o.lowerType(Type.fromInterned(nav.typeOf(ip))), |
| 2996 | 3000 | toLlvmGlobalAddressSpace(nav.getAddrspace(), zcu.getTarget()), |
| 2997 | 3001 | ); |
| 2998 | 3002 | gop.value_ptr.* = variable_index.ptrConst(&o.builder).global; |
| 2999 | 3003 | |
| 3000 | 3004 | // This is needed for declarations created by `@extern`. |
| 3001 | if (is_extern) { | |
| 3002 | variable_index.setLinkage(.external, &o.builder); | |
| 3003 | variable_index.setUnnamedAddr(.default, &o.builder); | |
| 3004 | if (is_threadlocal and !zcu.navFileScope(nav_index).mod.?.single_threaded) | |
| 3005 | variable_index.setThreadLocal(.generaldynamic, &o.builder); | |
| 3006 | if (is_weak_linkage) variable_index.setLinkage(.extern_weak, &o.builder); | |
| 3007 | if (is_dll_import) variable_index.setDllStorageClass(.dllimport, &o.builder); | |
| 3008 | } else { | |
| 3009 | variable_index.setLinkage(.internal, &o.builder); | |
| 3010 | variable_index.setUnnamedAddr(.unnamed_addr, &o.builder); | |
| 3011 | } | |
| 3005 | switch (linkage) { | |
| 3006 | .internal => { | |
| 3007 | variable_index.setLinkage(.internal, &o.builder); | |
| 3008 | variable_index.setUnnamedAddr(.unnamed_addr, &o.builder); | |
| 3009 | }, | |
| 3010 | .strong, .weak => { | |
| 3011 | variable_index.setLinkage(switch (linkage) { | |
| 3012 | .internal => unreachable, | |
| 3013 | .strong => .external, | |
| 3014 | .weak => .extern_weak, | |
| 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 | 3025 | return variable_index; |
| 3013 | 3026 | } |
| 3014 | 3027 | |
| ... | ... | @@ -4530,14 +4543,14 @@ pub const NavGen = struct { |
| 4530 | 4543 | const nav = ip.getNav(nav_index); |
| 4531 | 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)) { | |
| 4534 | .variable => |variable| .{ false, .none, variable.is_threadlocal, variable.is_weak_linkage, 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 }, | |
| 4536 | else => .{ false, .none, false, false, false, true, resolved.val, nav_index }, | |
| 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)) { | |
| 4547 | .variable => |variable| .{ .none, .internal, .default, variable.is_threadlocal, false, false, variable.init, variable.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 }, | |
| 4549 | else => .{ .none, .internal, .default, false, false, true, resolved.val, nav_index }, | |
| 4537 | 4550 | }; |
| 4538 | 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 | 4554 | _ = try o.resolveLlvmFunction(owner_nav); |
| 4542 | 4555 | } else { |
| 4543 | 4556 | const variable_index = try o.resolveGlobalNav(nav_index); |
| ... | ... | @@ -4549,6 +4562,7 @@ pub const NavGen = struct { |
| 4549 | 4562 | .none => .no_init, |
| 4550 | 4563 | else => try o.lowerValue(init_val), |
| 4551 | 4564 | }, &o.builder); |
| 4565 | variable_index.setVisibility(visibility, &o.builder); | |
| 4552 | 4566 | |
| 4553 | 4567 | const file_scope = zcu.navFileScopeIndex(nav_index); |
| 4554 | 4568 | const mod = zcu.fileByIndex(file_scope).mod.?; |
| ... | ... | @@ -4568,7 +4582,7 @@ pub const NavGen = struct { |
| 4568 | 4582 | line_number, |
| 4569 | 4583 | try o.lowerDebugType(ty), |
| 4570 | 4584 | variable_index, |
| 4571 | .{ .local = !is_extern }, | |
| 4585 | .{ .local = linkage == .internal }, | |
| 4572 | 4586 | ); |
| 4573 | 4587 | |
| 4574 | 4588 | const debug_expression = try o.builder.debugExpression(&.{}); |
| ... | ... | @@ -4583,38 +4597,47 @@ pub const NavGen = struct { |
| 4583 | 4597 | } |
| 4584 | 4598 | } |
| 4585 | 4599 | |
| 4586 | if (is_extern) { | |
| 4587 | const global_index = o.nav_map.get(nav_index).?; | |
| 4600 | switch (linkage) { | |
| 4601 | .internal => {}, | |
| 4602 | .strong, .weak => { | |
| 4603 | const global_index = o.nav_map.get(nav_index).?; | |
| 4588 | 4604 | |
| 4589 | const decl_name = decl_name: { | |
| 4590 | if (zcu.getTarget().cpu.arch.isWasm() and ty.zigTypeTag(zcu) == .@"fn") { | |
| 4591 | if (lib_name.toSlice(ip)) |lib_name_slice| { | |
| 4592 | 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 }); | |
| 4605 | const decl_name = decl_name: { | |
| 4606 | if (zcu.getTarget().cpu.arch.isWasm() and ty.zigTypeTag(zcu) == .@"fn") { | |
| 4607 | if (lib_name.toSlice(ip)) |lib_name_slice| { | |
| 4608 | if (!std.mem.eql(u8, lib_name_slice, "c")) { | |
| 4609 | break :decl_name try o.builder.strtabStringFmt("{}|{s}", .{ nav.name.fmt(ip), lib_name_slice }); | |
| 4610 | } | |
| 4594 | 4611 | } |
| 4595 | 4612 | } |
| 4596 | } | |
| 4597 | break :decl_name try o.builder.strtabString(nav.name.toSlice(ip)); | |
| 4598 | }; | |
| 4613 | break :decl_name try o.builder.strtabString(nav.name.toSlice(ip)); | |
| 4614 | }; | |
| 4599 | 4615 | |
| 4600 | if (o.builder.getGlobal(decl_name)) |other_global| { | |
| 4601 | if (other_global != global_index) { | |
| 4602 | // Another global already has this name; just use it in place of this global. | |
| 4603 | try global_index.replace(other_global, &o.builder); | |
| 4604 | return; | |
| 4616 | if (o.builder.getGlobal(decl_name)) |other_global| { | |
| 4617 | if (other_global != global_index) { | |
| 4618 | // Another global already has this name; just use it in place of this global. | |
| 4619 | try global_index.replace(other_global, &o.builder); | |
| 4620 | return; | |
| 4621 | } | |
| 4605 | 4622 | } |
| 4606 | } | |
| 4607 | 4623 | |
| 4608 | try global_index.rename(decl_name, &o.builder); | |
| 4609 | global_index.setLinkage(.external, &o.builder); | |
| 4610 | global_index.setUnnamedAddr(.default, &o.builder); | |
| 4611 | if (is_dll_import) { | |
| 4612 | global_index.setDllStorageClass(.dllimport, &o.builder); | |
| 4613 | } else if (zcu.comp.config.dll_export_fns) { | |
| 4614 | global_index.setDllStorageClass(.default, &o.builder); | |
| 4615 | } | |
| 4624 | try global_index.rename(decl_name, &o.builder); | |
| 4625 | global_index.setUnnamedAddr(.default, &o.builder); | |
| 4626 | if (is_dll_import) { | |
| 4627 | global_index.setDllStorageClass(.dllimport, &o.builder); | |
| 4628 | } else if (zcu.comp.config.dll_export_fns) { | |
| 4629 | global_index.setDllStorageClass(.default, &o.builder); | |
| 4630 | } | |
| 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 | 5046 | |
| 5024 | 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 | 5051 | .inferred_alloc, .inferred_alloc_comptime => unreachable, |
| 5029 | 5052 | |
| ... | ... | @@ -8122,7 +8145,7 @@ pub const FuncGen = struct { |
| 8122 | 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 | 8149 | const o = fg.ng.object; |
| 8127 | 8150 | const ty_nav = fg.air.instructions.items(.data)[@intFromEnum(inst)].ty_nav; |
| 8128 | 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 | 785 | } |
| 786 | 786 | |
| 787 | 787 | const Index = enum(u32) { |
| 788 | //got_proc, | |
| 789 | 788 | _, |
| 790 | 789 | |
| 791 | 790 | const Optional = enum(u32) { |
| ... | ... | @@ -1041,7 +1040,7 @@ const Entry = struct { |
| 1041 | 1040 | const symbol = zo.symbol(reloc.target_sym); |
| 1042 | 1041 | try dwarf.resolveReloc( |
| 1043 | 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 | 1044 | if (symbol.flags.is_tls) elf_file.dtpAddress() else 0), |
| 1046 | 1045 | @intFromEnum(dwarf.address_size), |
| 1047 | 1046 | ); |
| ... | ... | @@ -1052,7 +1051,7 @@ const Entry = struct { |
| 1052 | 1051 | const ref = zo.getSymbolRef(reloc.target_sym, macho_file); |
| 1053 | 1052 | try dwarf.resolveReloc( |
| 1054 | 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 | 1055 | @intFromEnum(dwarf.address_size), |
| 1057 | 1056 | ); |
| 1058 | 1057 | } |
| ... | ... | @@ -1081,27 +1080,12 @@ const CrossSectionReloc = struct { |
| 1081 | 1080 | const ExternalReloc = struct { |
| 1082 | 1081 | source_off: u32 = 0, |
| 1083 | 1082 | target_sym: u32, |
| 1084 | target_off: enum(u64) { | |
| 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, | |
| 1083 | target_off: u64 = 0, | |
| 1099 | 1084 | }; |
| 1100 | 1085 | |
| 1101 | 1086 | pub const Loc = union(enum) { |
| 1102 | 1087 | empty, |
| 1103 | 1088 | addr_reloc: u32, |
| 1104 | got_reloc: u32, | |
| 1105 | 1089 | deref: *const Loc, |
| 1106 | 1090 | constu: u64, |
| 1107 | 1091 | consts: i64, |
| ... | ... | @@ -1166,10 +1150,6 @@ pub const Loc = union(enum) { |
| 1166 | 1150 | try addr.write(adapter); |
| 1167 | 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 | 1153 | .constu => |constu| if (std.math.cast(u5, constu)) |lit| { |
| 1174 | 1154 | try writer.writeByte(@as(u8, DW.OP.lit0) + lit); |
| 1175 | 1155 | } else if (std.math.cast(u8, constu)) |const1u| { |
| ... | ... | @@ -1766,9 +1746,6 @@ pub const WipNav = struct { |
| 1766 | 1746 | fn endian(_: ExprLocCounter) std.builtin.Endian { |
| 1767 | 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 | 1749 | fn addrSym(counter: *ExprLocCounter, _: u32) error{}!void { |
| 1773 | 1750 | counter.stream.bytes_written += @intFromEnum(counter.address_size); |
| 1774 | 1751 | } |
| ... | ... | @@ -1789,14 +1766,6 @@ pub const WipNav = struct { |
| 1789 | 1766 | fn endian(ctx: @This()) std.builtin.Endian { |
| 1790 | 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 | 1769 | fn addrSym(ctx: @This(), sym_index: u32) UpdateError!void { |
| 1801 | 1770 | try ctx.wip_nav.infoAddrSym(sym_index, 0); |
| 1802 | 1771 | } |
| ... | ... | @@ -1812,7 +1781,7 @@ pub const WipNav = struct { |
| 1812 | 1781 | try wip_nav.infoExternalReloc(.{ |
| 1813 | 1782 | .source_off = @intCast(wip_nav.debug_info.items.len), |
| 1814 | 1783 | .target_sym = sym_index, |
| 1815 | .target_off = .rel(sym_off), | |
| 1784 | .target_off = sym_off, | |
| 1816 | 1785 | }); |
| 1817 | 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 | 1798 | fn endian(ctx: @This()) std.builtin.Endian { |
| 1830 | 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 | 1801 | fn addrSym(ctx: @This(), sym_index: u32) UpdateError!void { |
| 1841 | 1802 | try ctx.wip_nav.frameAddrSym(sym_index, 0); |
| 1842 | 1803 | } |
| ... | ... | @@ -1852,7 +1813,7 @@ pub const WipNav = struct { |
| 1852 | 1813 | try wip_nav.frameExternalReloc(.{ |
| 1853 | 1814 | .source_off = @intCast(wip_nav.debug_frame.items.len), |
| 1854 | 1815 | .target_sym = sym_index, |
| 1855 | .target_off = .rel(sym_off), | |
| 1816 | .target_off = sym_off, | |
| 1856 | 1817 | }); |
| 1857 | 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 | 2299 | const mod_gop = try dwarf.mods.getOrPut(dwarf.gpa, mod); |
| 2339 | 2300 | const unit: Unit.Index = @enumFromInt(mod_gop.index); |
| 2340 | 2301 | if (!mod_gop.found_existing) { |
| 2341 | { | |
| 2342 | errdefer _ = dwarf.mods.pop(); | |
| 2343 | mod_gop.value_ptr.* = .{ | |
| 2344 | .root_dir_path = undefined, | |
| 2345 | .dirs = .empty, | |
| 2346 | .files = .empty, | |
| 2347 | }; | |
| 2348 | errdefer mod_gop.value_ptr.dirs.deinit(dwarf.gpa); | |
| 2349 | try mod_gop.value_ptr.dirs.putNoClobber(dwarf.gpa, unit, {}); | |
| 2350 | assert(try dwarf.debug_aranges.section.addUnit( | |
| 2351 | DebugAranges.headerBytes(dwarf), | |
| 2352 | DebugAranges.trailerBytes(dwarf), | |
| 2353 | dwarf, | |
| 2354 | ) == unit); | |
| 2355 | errdefer dwarf.debug_aranges.section.popUnit(dwarf.gpa); | |
| 2356 | assert(try dwarf.debug_frame.section.addUnit( | |
| 2357 | DebugFrame.headerBytes(dwarf), | |
| 2358 | DebugFrame.trailerBytes(dwarf), | |
| 2359 | dwarf, | |
| 2360 | ) == unit); | |
| 2361 | errdefer dwarf.debug_frame.section.popUnit(dwarf.gpa); | |
| 2362 | assert(try dwarf.debug_info.section.addUnit( | |
| 2363 | DebugInfo.headerBytes(dwarf), | |
| 2364 | DebugInfo.trailer_bytes, | |
| 2365 | dwarf, | |
| 2366 | ) == unit); | |
| 2367 | errdefer dwarf.debug_info.section.popUnit(dwarf.gpa); | |
| 2368 | assert(try dwarf.debug_line.section.addUnit( | |
| 2369 | DebugLine.headerBytes(dwarf, 5, 25), | |
| 2370 | DebugLine.trailer_bytes, | |
| 2371 | dwarf, | |
| 2372 | ) == unit); | |
| 2373 | errdefer dwarf.debug_line.section.popUnit(dwarf.gpa); | |
| 2374 | assert(try dwarf.debug_loclists.section.addUnit( | |
| 2375 | DebugLocLists.headerBytes(dwarf), | |
| 2376 | DebugLocLists.trailer_bytes, | |
| 2377 | dwarf, | |
| 2378 | ) == unit); | |
| 2379 | errdefer dwarf.debug_loclists.section.popUnit(dwarf.gpa); | |
| 2380 | assert(try dwarf.debug_rnglists.section.addUnit( | |
| 2381 | DebugRngLists.headerBytes(dwarf), | |
| 2382 | DebugRngLists.trailer_bytes, | |
| 2383 | dwarf, | |
| 2384 | ) == unit); | |
| 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 | //} | |
| 2302 | errdefer _ = dwarf.mods.pop(); | |
| 2303 | mod_gop.value_ptr.* = .{ | |
| 2304 | .root_dir_path = undefined, | |
| 2305 | .dirs = .empty, | |
| 2306 | .files = .empty, | |
| 2307 | }; | |
| 2308 | errdefer mod_gop.value_ptr.dirs.deinit(dwarf.gpa); | |
| 2309 | try mod_gop.value_ptr.dirs.putNoClobber(dwarf.gpa, unit, {}); | |
| 2310 | assert(try dwarf.debug_aranges.section.addUnit( | |
| 2311 | DebugAranges.headerBytes(dwarf), | |
| 2312 | DebugAranges.trailerBytes(dwarf), | |
| 2313 | dwarf, | |
| 2314 | ) == unit); | |
| 2315 | errdefer dwarf.debug_aranges.section.popUnit(dwarf.gpa); | |
| 2316 | assert(try dwarf.debug_frame.section.addUnit( | |
| 2317 | DebugFrame.headerBytes(dwarf), | |
| 2318 | DebugFrame.trailerBytes(dwarf), | |
| 2319 | dwarf, | |
| 2320 | ) == unit); | |
| 2321 | errdefer dwarf.debug_frame.section.popUnit(dwarf.gpa); | |
| 2322 | assert(try dwarf.debug_info.section.addUnit( | |
| 2323 | DebugInfo.headerBytes(dwarf), | |
| 2324 | DebugInfo.trailer_bytes, | |
| 2325 | dwarf, | |
| 2326 | ) == unit); | |
| 2327 | errdefer dwarf.debug_info.section.popUnit(dwarf.gpa); | |
| 2328 | assert(try dwarf.debug_line.section.addUnit( | |
| 2329 | DebugLine.headerBytes(dwarf, 5, 25), | |
| 2330 | DebugLine.trailer_bytes, | |
| 2331 | dwarf, | |
| 2332 | ) == unit); | |
| 2333 | errdefer dwarf.debug_line.section.popUnit(dwarf.gpa); | |
| 2334 | assert(try dwarf.debug_loclists.section.addUnit( | |
| 2335 | DebugLocLists.headerBytes(dwarf), | |
| 2336 | DebugLocLists.trailer_bytes, | |
| 2337 | dwarf, | |
| 2338 | ) == unit); | |
| 2339 | errdefer dwarf.debug_loclists.section.popUnit(dwarf.gpa); | |
| 2340 | assert(try dwarf.debug_rnglists.section.addUnit( | |
| 2341 | DebugRngLists.headerBytes(dwarf), | |
| 2342 | DebugRngLists.trailer_bytes, | |
| 2343 | dwarf, | |
| 2344 | ) == unit); | |
| 2345 | errdefer dwarf.debug_rnglists.section.popUnit(dwarf.gpa); | |
| 2416 | 2346 | } |
| 2417 | 2347 | return unit; |
| 2418 | 2348 | } |
| ... | ... | @@ -2510,16 +2440,7 @@ fn initWipNavInner( |
| 2510 | 2440 | try wip_nav.strp(nav.fqn.toSlice(ip)); |
| 2511 | 2441 | const ty: Type = nav_val.typeOf(zcu); |
| 2512 | 2442 | const addr: Loc = .{ .addr_reloc = sym_index }; |
| 2513 | const loc: Loc = loc: { | |
| 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 | }; | |
| 2443 | const loc: Loc = if (decl.is_threadlocal) .{ .form_tls_address = &addr } else addr; | |
| 2523 | 2444 | switch (decl.kind) { |
| 2524 | 2445 | .unnamed_test, .@"test", .decltest, .@"comptime", .@"usingnamespace" => unreachable, |
| 2525 | 2446 | .@"const" => { |
| ... | ... | @@ -2605,7 +2526,7 @@ fn initWipNavInner( |
| 2605 | 2526 | try wip_nav.infoAddrSym(sym_index, 0); |
| 2606 | 2527 | wip_nav.func_high_pc = @intCast(wip_nav.debug_info.items.len); |
| 2607 | 2528 | try diw.writeInt(u32, 0, dwarf.endian); |
| 2608 | const target = file.mod.?.resolved_target.result; | |
| 2529 | const target = mod.resolved_target.result; | |
| 2609 | 2530 | try uleb128(diw, switch (nav.status.fully_resolved.alignment) { |
| 2610 | 2531 | .none => target_info.defaultFunctionAlignment(target), |
| 2611 | 2532 | else => |a| a.maxStrict(target_info.minFunctionAlignment(target)), |
| ... | ... | @@ -2742,7 +2663,7 @@ pub fn finishWipNavFunc( |
| 2742 | 2663 | .{ |
| 2743 | 2664 | .source_off = 1 + @intFromEnum(dwarf.address_size), |
| 2744 | 2665 | .target_sym = wip_nav.func_sym_index, |
| 2745 | .target_off = .rel(code_size), | |
| 2666 | .target_off = code_size, | |
| 2746 | 2667 | }, |
| 2747 | 2668 | }); |
| 2748 | 2669 | try dwarf.debug_rnglists.section.replaceEntry( |
| ... | ... | @@ -4981,7 +4902,6 @@ const AbbrevCode = enum { |
| 4981 | 4902 | comptime_value_field_comptime_state, |
| 4982 | 4903 | comptime_value_elem_runtime_bits, |
| 4983 | 4904 | comptime_value_elem_comptime_state, |
| 4984 | //proc, | |
| 4985 | 4905 | |
| 4986 | 4906 | const decl_bytes = uleb128Bytes(@intFromEnum(AbbrevCode.decl_instance_func_generic)); |
| 4987 | 4907 | comptime { |
| ... | ... | @@ -5851,12 +5771,6 @@ const AbbrevCode = enum { |
| 5851 | 5771 | .{ .ZIG_comptime_value, .ref_addr }, |
| 5852 | 5772 | }, |
| 5853 | 5773 | }, |
| 5854 | //.proc = .{ | |
| 5855 | // .tag = .dwarf_procedure, | |
| 5856 | // .attrs = &.{ | |
| 5857 | // .{ .location, .exprloc }, | |
| 5858 | // }, | |
| 5859 | //}, | |
| 5860 | 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 | 959 | self.rela_plt.clearRetainingCapacity(); |
| 960 | 960 | |
| 961 | 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 | 968 | var has_reloc_errors = false; |
| 963 | 969 | for (zo.atoms_indexes.items) |atom_index| { |
| 964 | 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 | 975 | const code = try zo.codeAlloc(self, atom_index); |
| 970 | 976 | defer gpa.free(code); |
| 971 | 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 | 982 | error.RelocFailure, error.RelaxFailure => has_reloc_errors = true, |
| 974 | 983 | error.UnsupportedCpuArch => { |
| 975 | 984 | try self.reportUnsupportedCpuArch(); |
| ... | ... | @@ -980,6 +989,8 @@ fn flushModuleInner(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id) !void { |
| 980 | 989 | try self.pwriteAll(code, file_offset); |
| 981 | 990 | } |
| 982 | 991 | |
| 992 | try self.reportUndefinedSymbols(&undefs); | |
| 993 | ||
| 983 | 994 | if (has_reloc_errors) return error.LinkFailure; |
| 984 | 995 | } |
| 985 | 996 | |
| ... | ... | @@ -1392,11 +1403,9 @@ fn scanRelocs(self: *Elf) !void { |
| 1392 | 1403 | const gpa = self.base.comp.gpa; |
| 1393 | 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 | 1407 | defer { |
| 1397 | for (undefs.values()) |*refs| { | |
| 1398 | refs.deinit(); | |
| 1399 | } | |
| 1408 | for (undefs.values()) |*refs| refs.deinit(); | |
| 1400 | 1409 | undefs.deinit(); |
| 1401 | 1410 | } |
| 1402 | 1411 | |
| ... | ... | @@ -2702,15 +2711,16 @@ fn initSyntheticSections(self: *Elf) !void { |
| 2702 | 2711 | }); |
| 2703 | 2712 | } |
| 2704 | 2713 | |
| 2705 | const needs_interp = blk: { | |
| 2706 | // On Ubuntu with musl-gcc, we get a weird combo of options looking like this: | |
| 2707 | // -dynamic-linker=<path> -static | |
| 2708 | // In this case, if we do generate .interp section and segment, we will get | |
| 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; | |
| 2714 | const is_exe_or_dyn_lib = switch (comp.config.output_mode) { | |
| 2715 | .Exe => true, | |
| 2716 | .Lib => comp.config.link_mode == .dynamic, | |
| 2717 | .Obj => false, | |
| 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 | 2724 | if (needs_interp and self.section_indexes.interp == null) { |
| 2715 | 2725 | self.section_indexes.interp = try self.addSection(.{ |
| 2716 | 2726 | .name = try self.insertShString(".interp"), |
| ... | ... | @@ -3707,11 +3717,9 @@ fn allocateSpecialPhdrs(self: *Elf) void { |
| 3707 | 3717 | fn writeAtoms(self: *Elf) !void { |
| 3708 | 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 | 3721 | defer { |
| 3712 | for (undefs.values()) |*refs| { | |
| 3713 | refs.deinit(); | |
| 3714 | } | |
| 3722 | for (undefs.values()) |*refs| refs.deinit(); | |
| 3715 | 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 | 497 | } |
| 498 | 498 | |
| 499 | 499 | fn outputType(elf_file: *Elf) u2 { |
| 500 | const comp = elf_file.base.comp; | |
| 501 | 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 | 503 | .Obj => unreachable, |
| 504 | 504 | .Lib => 0, |
| 505 | 505 | .Exe => switch (elf_file.getTarget().os.tag) { |
| 506 | 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 | 463 | for (entry.external_relocs.items) |reloc| { |
| 464 | 464 | const target_sym = self.symbol(reloc.target_sym); |
| 465 | 465 | const r_offset = entry_off + reloc.source_off; |
| 466 | const r_addend: i64 = switch (reloc.target_off) { | |
| 467 | .none, .got => 0, | |
| 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); | |
| 466 | const r_addend: i64 = @intCast(reloc.target_off); | |
| 467 | const r_type = relocation.dwarf.externalRelocType(target_sym.*, sect_index, dwarf.address_size, cpu_arch); | |
| 471 | 468 | atom_ptr.addRelocAssumeCapacity(.{ |
| 472 | 469 | .r_offset = r_offset, |
| 473 | 470 | .r_addend = r_addend, |
| ... | ... | @@ -660,6 +657,7 @@ pub fn scanRelocs(self: *ZigObject, elf_file: *Elf, undefs: anytype) !void { |
| 660 | 657 | const atom_ptr = self.atom(atom_index) orelse continue; |
| 661 | 658 | if (!atom_ptr.alive) continue; |
| 662 | 659 | const shdr = atom_ptr.inputShdr(elf_file); |
| 660 | if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue; | |
| 663 | 661 | if (shdr.sh_type == elf.SHT_NOBITS) continue; |
| 664 | 662 | if (atom_ptr.scanRelocsRequiresCode(elf_file)) { |
| 665 | 663 | // TODO ideally we don't have to fetch the code here. |
| ... | ... | @@ -950,7 +948,7 @@ pub fn getNavVAddr( |
| 950 | 948 | .dwarf => |wip_nav| try wip_nav.infoExternalReloc(.{ |
| 951 | 949 | .source_off = @intCast(reloc_info.offset), |
| 952 | 950 | .target_sym = this_sym_index, |
| 953 | .target_off = .rel(reloc_info.addend), | |
| 951 | .target_off = reloc_info.addend, | |
| 954 | 952 | }), |
| 955 | 953 | .plan9 => unreachable, |
| 956 | 954 | .none => unreachable, |
| ... | ... | @@ -983,7 +981,7 @@ pub fn getUavVAddr( |
| 983 | 981 | .dwarf => |wip_nav| try wip_nav.infoExternalReloc(.{ |
| 984 | 982 | .source_off = @intCast(reloc_info.offset), |
| 985 | 983 | .target_sym = sym_index, |
| 986 | .target_off = .rel(reloc_info.addend), | |
| 984 | .target_off = reloc_info.addend, | |
| 987 | 985 | }), |
| 988 | 986 | .plan9 => unreachable, |
| 989 | 987 | .none => unreachable, |
src/link/Elf/relocation.zig+1-2| ... | ... | @@ -108,13 +108,12 @@ pub const dwarf = struct { |
| 108 | 108 | |
| 109 | 109 | pub fn externalRelocType( |
| 110 | 110 | target: Symbol, |
| 111 | is_got: bool, | |
| 112 | 111 | source_section: Dwarf.Section.Index, |
| 113 | 112 | address_size: Dwarf.AddressSize, |
| 114 | 113 | cpu_arch: std.Target.Cpu.Arch, |
| 115 | 114 | ) u32 { |
| 116 | 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 | 117 | else => switch (address_size) { |
| 119 | 118 | .@"32" => if (target.flags.is_tls) .DTPOFF32 else .@"32", |
| 120 | 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 | 648 | .dwarf => |wip_nav| try wip_nav.infoExternalReloc(.{ |
| 649 | 649 | .source_off = @intCast(reloc_info.offset), |
| 650 | 650 | .target_sym = sym_index, |
| 651 | .target_off = .rel(reloc_info.addend), | |
| 651 | .target_off = reloc_info.addend, | |
| 652 | 652 | }), |
| 653 | 653 | .plan9 => unreachable, |
| 654 | 654 | .none => unreachable, |
| ... | ... | @@ -688,7 +688,7 @@ pub fn getUavVAddr( |
| 688 | 688 | .dwarf => |wip_nav| try wip_nav.infoExternalReloc(.{ |
| 689 | 689 | .source_off = @intCast(reloc_info.offset), |
| 690 | 690 | .target_sym = sym_index, |
| 691 | .target_off = .rel(reloc_info.addend), | |
| 691 | .target_off = reloc_info.addend, | |
| 692 | 692 | }), |
| 693 | 693 | .plan9 => unreachable, |
| 694 | 694 | .none => unreachable, |
src/link/Wasm.zig+1-1| ... | ... | @@ -2376,7 +2376,7 @@ pub const FunctionImportId = enum(u32) { |
| 2376 | 2376 | const zcu = wasm.base.comp.zcu.?; |
| 2377 | 2377 | const ip = &zcu.intern_pool; |
| 2378 | 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 | 117 | // tmp.zig:37:38: note: imported here |
| 118 | 118 | // neg_inf.zon:1:1: error: expected type '?u8' |
| 119 | 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 | 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 | 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 | 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 | 15 | // error |
| 16 | 16 | // |
| 17 | 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 | 19 | // :4:16: note: struct requires comptime because of this field |
| 20 | 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 | 16 | // |
| 17 | 17 | // :3:6: error: no field or member function named 'copy' in '[]const u8' |
| 18 | 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 | 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 | |
| 7 | 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 | 10 | // :3:16: note: struct declared here |
| 11 | 11 | // :1:11: note: struct declared here |
test/cases/compile_errors/redundant_try.zig+2-2| ... | ... | @@ -44,9 +44,9 @@ comptime { |
| 44 | 44 | // |
| 45 | 45 | // :5:23: error: expected error union type, found 'comptime_int' |
| 46 | 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 | 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 | 50 | // :20:27: note: struct declared here |
| 51 | 51 | // :25:23: error: expected error union type, found 'struct { comptime *const [5:0]u8 = "hello" }' |
| 52 | 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 | 1598 | break :blk [_]CAbiTarget{ |
| 1599 | 1599 | // Native Targets |
| 1600 | 1600 | |
| 1601 | .{}, | |
| 1601 | .{ | |
| 1602 | .use_llvm = true, | |
| 1603 | }, | |
| 1602 | 1604 | |
| 1603 | 1605 | // Linux Targets |
| 1604 | 1606 | |
| ... | ... | @@ -1837,7 +1839,6 @@ const c_abi_targets = blk: { |
| 1837 | 1839 | .abi = .musl, |
| 1838 | 1840 | }, |
| 1839 | 1841 | .use_llvm = false, |
| 1840 | .use_lld = false, | |
| 1841 | 1842 | .c_defines = &.{"ZIG_BACKEND_STAGE2_X86_64"}, |
| 1842 | 1843 | }, |
| 1843 | 1844 | .{ |
| ... | ... | @@ -1848,7 +1849,6 @@ const c_abi_targets = blk: { |
| 1848 | 1849 | .abi = .musl, |
| 1849 | 1850 | }, |
| 1850 | 1851 | .use_llvm = false, |
| 1851 | .use_lld = false, | |
| 1852 | 1852 | .strip = true, |
| 1853 | 1853 | .c_defines = &.{"ZIG_BACKEND_STAGE2_X86_64"}, |
| 1854 | 1854 | }, |
| ... | ... | @@ -1860,7 +1860,6 @@ const c_abi_targets = blk: { |
| 1860 | 1860 | .abi = .musl, |
| 1861 | 1861 | }, |
| 1862 | 1862 | .use_llvm = false, |
| 1863 | .use_lld = false, | |
| 1864 | 1863 | .pic = true, |
| 1865 | 1864 | .c_defines = &.{"ZIG_BACKEND_STAGE2_X86_64"}, |
| 1866 | 1865 | }, |
| ... | ... | @@ -1870,6 +1869,7 @@ const c_abi_targets = blk: { |
| 1870 | 1869 | .os_tag = .linux, |
| 1871 | 1870 | .abi = .musl, |
| 1872 | 1871 | }, |
| 1872 | .use_llvm = true, | |
| 1873 | 1873 | }, |
| 1874 | 1874 | .{ |
| 1875 | 1875 | .target = .{ |
| ... | ... | @@ -1877,6 +1877,7 @@ const c_abi_targets = blk: { |
| 1877 | 1877 | .os_tag = .linux, |
| 1878 | 1878 | .abi = .muslx32, |
| 1879 | 1879 | }, |
| 1880 | .use_llvm = true, | |
| 1880 | 1881 | }, |
| 1881 | 1882 | |
| 1882 | 1883 | // WASI Targets |