| author | |
| committer | |
| log | aecebf38acc8835db21eeea7b53e4ee26ec739a8 |
| tree | 132a3982487ae7bb1a0210a4ff2b7cd7a2934855 |
| parent | 0e2b9ac7770df07212d4d1cbfb15c3aaed0bef18 |
* prepare compiler-rt to support being compiled by stage2
- put in a few minor workarounds that will be removed later, such as
using `builtin.stage2_arch` rather than `builtin.cpu.arch`.
- only try to export a few symbols for now - we'll move more symbols
over to the "working in stage2" section as they become functional
and gain test coverage.
- use `inline fn` at function declarations rather than `@call` with an
always_inline modifier at the callsites, to avoid depending on the
anonymous array literal syntax language feature (for now).
* AIR: replace floatcast instruction with fptrunc and fpext for
shortening and widening floating point values, respectively.
* Introduce a new ZIR instruction, `export_value`, which implements
`@export` for the case when the thing to be exported is a local
comptime value that points to a function.
- AstGen: fix `@export` not properly reporting ambiguous decl
references.
* Sema: handle ExportOptions linkage. The value is now available to all
backends.
- Implement setting global linkage as appropriate in the LLVM
backend. I did not yet inspect the LLVM IR, so this still needs to
be audited. There is already a pending task to make sure the alias
stuff is working as intended, and this is related.
- Sema almost handles section, just a tiny bit more code is needed in
`resolveExportOptions`.
* Sema: implement float widening and shortening for both `@floatCast`
and float coercion.
- Implement the LLVM backend code for this as well.21 files changed, 1723 insertions(+), 1547 deletions(-)
lib/std/special/compiler_rt.zig+591-573| ... | @@ -1,171 +1,24 @@ | ... | @@ -1,171 +1,24 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const builtin = std.builtin; | 2 | const builtin = @import("builtin"); |
| 3 | const is_test = builtin.is_test; | 3 | const is_test = builtin.is_test; |
| 4 | const os_tag = std.Target.current.os.tag; | 4 | const os_tag = std.Target.current.os.tag; |
| 5 | const arch = std.Target.current.cpu.arch; | 5 | const arch = builtin.stage2_arch; |
| 6 | const abi = std.Target.current.abi; | 6 | const abi = std.Target.current.abi; |
| 7 | 7 | ||
| 8 | const is_gnu = abi.isGnu(); | 8 | const is_gnu = abi.isGnu(); |
| 9 | const is_mingw = os_tag == .windows and is_gnu; | 9 | const is_mingw = os_tag == .windows and is_gnu; |
| 10 | 10 | ||
| 11 | comptime { | 11 | const linkage = if (is_test) |
| 12 | const linkage = if (is_test) builtin.GlobalLinkage.Internal else builtin.GlobalLinkage.Weak; | 12 | std.builtin.GlobalLinkage.Internal |
| 13 | const strong_linkage = if (is_test) builtin.GlobalLinkage.Internal else builtin.GlobalLinkage.Strong; | 13 | else |
| 14 | 14 | std.builtin.GlobalLinkage.Weak; | |
| 15 | switch (arch) { | ||
| 16 | .i386, | ||
| 17 | .x86_64, | ||
| 18 | => { | ||
| 19 | const zig_probe_stack = @import("compiler_rt/stack_probe.zig").zig_probe_stack; | ||
| 20 | @export(zig_probe_stack, .{ | ||
| 21 | .name = "__zig_probe_stack", | ||
| 22 | .linkage = linkage, | ||
| 23 | }); | ||
| 24 | }, | ||
| 25 | |||
| 26 | else => {}, | ||
| 27 | } | ||
| 28 | 15 | ||
| 29 | // __clear_cache manages its own logic about whether to be exported or not. | 16 | const strong_linkage = if (is_test) |
| 30 | _ = @import("compiler_rt/clear_cache.zig").clear_cache; | 17 | std.builtin.GlobalLinkage.Internal |
| 31 | 18 | else | |
| 32 | const __lesf2 = @import("compiler_rt/compareXf2.zig").__lesf2; | 19 | std.builtin.GlobalLinkage.Strong; |
| 33 | @export(__lesf2, .{ .name = "__lesf2", .linkage = linkage }); | ||
| 34 | const __ledf2 = @import("compiler_rt/compareXf2.zig").__ledf2; | ||
| 35 | @export(__ledf2, .{ .name = "__ledf2", .linkage = linkage }); | ||
| 36 | const __letf2 = @import("compiler_rt/compareXf2.zig").__letf2; | ||
| 37 | @export(__letf2, .{ .name = "__letf2", .linkage = linkage }); | ||
| 38 | |||
| 39 | const __gesf2 = @import("compiler_rt/compareXf2.zig").__gesf2; | ||
| 40 | @export(__gesf2, .{ .name = "__gesf2", .linkage = linkage }); | ||
| 41 | const __gedf2 = @import("compiler_rt/compareXf2.zig").__gedf2; | ||
| 42 | @export(__gedf2, .{ .name = "__gedf2", .linkage = linkage }); | ||
| 43 | const __getf2 = @import("compiler_rt/compareXf2.zig").__getf2; | ||
| 44 | @export(__getf2, .{ .name = "__getf2", .linkage = linkage }); | ||
| 45 | |||
| 46 | if (!is_test) { | ||
| 47 | @export(__lesf2, .{ .name = "__cmpsf2", .linkage = linkage }); | ||
| 48 | @export(__ledf2, .{ .name = "__cmpdf2", .linkage = linkage }); | ||
| 49 | @export(__letf2, .{ .name = "__cmptf2", .linkage = linkage }); | ||
| 50 | |||
| 51 | const __eqsf2 = @import("compiler_rt/compareXf2.zig").__eqsf2; | ||
| 52 | @export(__eqsf2, .{ .name = "__eqsf2", .linkage = linkage }); | ||
| 53 | const __eqdf2 = @import("compiler_rt/compareXf2.zig").__eqdf2; | ||
| 54 | @export(__eqdf2, .{ .name = "__eqdf2", .linkage = linkage }); | ||
| 55 | @export(__letf2, .{ .name = "__eqtf2", .linkage = linkage }); | ||
| 56 | |||
| 57 | const __ltsf2 = @import("compiler_rt/compareXf2.zig").__ltsf2; | ||
| 58 | @export(__ltsf2, .{ .name = "__ltsf2", .linkage = linkage }); | ||
| 59 | const __ltdf2 = @import("compiler_rt/compareXf2.zig").__ltdf2; | ||
| 60 | @export(__ltdf2, .{ .name = "__ltdf2", .linkage = linkage }); | ||
| 61 | @export(__letf2, .{ .name = "__lttf2", .linkage = linkage }); | ||
| 62 | |||
| 63 | const __nesf2 = @import("compiler_rt/compareXf2.zig").__nesf2; | ||
| 64 | @export(__nesf2, .{ .name = "__nesf2", .linkage = linkage }); | ||
| 65 | const __nedf2 = @import("compiler_rt/compareXf2.zig").__nedf2; | ||
| 66 | @export(__nedf2, .{ .name = "__nedf2", .linkage = linkage }); | ||
| 67 | @export(__letf2, .{ .name = "__netf2", .linkage = linkage }); | ||
| 68 | |||
| 69 | const __gtsf2 = @import("compiler_rt/compareXf2.zig").__gtsf2; | ||
| 70 | @export(__gtsf2, .{ .name = "__gtsf2", .linkage = linkage }); | ||
| 71 | const __gtdf2 = @import("compiler_rt/compareXf2.zig").__gtdf2; | ||
| 72 | @export(__gtdf2, .{ .name = "__gtdf2", .linkage = linkage }); | ||
| 73 | @export(__getf2, .{ .name = "__gttf2", .linkage = linkage }); | ||
| 74 | |||
| 75 | const __extendhfsf2 = @import("compiler_rt/extendXfYf2.zig").__extendhfsf2; | ||
| 76 | @export(__extendhfsf2, .{ .name = "__gnu_h2f_ieee", .linkage = linkage }); | ||
| 77 | const __truncsfhf2 = @import("compiler_rt/truncXfYf2.zig").__truncsfhf2; | ||
| 78 | @export(__truncsfhf2, .{ .name = "__gnu_f2h_ieee", .linkage = linkage }); | ||
| 79 | } | ||
| 80 | |||
| 81 | const __unordsf2 = @import("compiler_rt/compareXf2.zig").__unordsf2; | ||
| 82 | @export(__unordsf2, .{ .name = "__unordsf2", .linkage = linkage }); | ||
| 83 | const __unorddf2 = @import("compiler_rt/compareXf2.zig").__unorddf2; | ||
| 84 | @export(__unorddf2, .{ .name = "__unorddf2", .linkage = linkage }); | ||
| 85 | const __unordtf2 = @import("compiler_rt/compareXf2.zig").__unordtf2; | ||
| 86 | @export(__unordtf2, .{ .name = "__unordtf2", .linkage = linkage }); | ||
| 87 | |||
| 88 | const __addsf3 = @import("compiler_rt/addXf3.zig").__addsf3; | ||
| 89 | @export(__addsf3, .{ .name = "__addsf3", .linkage = linkage }); | ||
| 90 | const __adddf3 = @import("compiler_rt/addXf3.zig").__adddf3; | ||
| 91 | @export(__adddf3, .{ .name = "__adddf3", .linkage = linkage }); | ||
| 92 | const __addtf3 = @import("compiler_rt/addXf3.zig").__addtf3; | ||
| 93 | @export(__addtf3, .{ .name = "__addtf3", .linkage = linkage }); | ||
| 94 | const __subsf3 = @import("compiler_rt/addXf3.zig").__subsf3; | ||
| 95 | @export(__subsf3, .{ .name = "__subsf3", .linkage = linkage }); | ||
| 96 | const __subdf3 = @import("compiler_rt/addXf3.zig").__subdf3; | ||
| 97 | @export(__subdf3, .{ .name = "__subdf3", .linkage = linkage }); | ||
| 98 | const __subtf3 = @import("compiler_rt/addXf3.zig").__subtf3; | ||
| 99 | @export(__subtf3, .{ .name = "__subtf3", .linkage = linkage }); | ||
| 100 | |||
| 101 | const __mulsf3 = @import("compiler_rt/mulXf3.zig").__mulsf3; | ||
| 102 | @export(__mulsf3, .{ .name = "__mulsf3", .linkage = linkage }); | ||
| 103 | const __muldf3 = @import("compiler_rt/mulXf3.zig").__muldf3; | ||
| 104 | @export(__muldf3, .{ .name = "__muldf3", .linkage = linkage }); | ||
| 105 | const __multf3 = @import("compiler_rt/mulXf3.zig").__multf3; | ||
| 106 | @export(__multf3, .{ .name = "__multf3", .linkage = linkage }); | ||
| 107 | |||
| 108 | const __divsf3 = @import("compiler_rt/divsf3.zig").__divsf3; | ||
| 109 | @export(__divsf3, .{ .name = "__divsf3", .linkage = linkage }); | ||
| 110 | const __divdf3 = @import("compiler_rt/divdf3.zig").__divdf3; | ||
| 111 | @export(__divdf3, .{ .name = "__divdf3", .linkage = linkage }); | ||
| 112 | const __divtf3 = @import("compiler_rt/divtf3.zig").__divtf3; | ||
| 113 | @export(__divtf3, .{ .name = "__divtf3", .linkage = linkage }); | ||
| 114 | |||
| 115 | const __ashldi3 = @import("compiler_rt/shift.zig").__ashldi3; | ||
| 116 | @export(__ashldi3, .{ .name = "__ashldi3", .linkage = linkage }); | ||
| 117 | const __ashlti3 = @import("compiler_rt/shift.zig").__ashlti3; | ||
| 118 | @export(__ashlti3, .{ .name = "__ashlti3", .linkage = linkage }); | ||
| 119 | const __ashrdi3 = @import("compiler_rt/shift.zig").__ashrdi3; | ||
| 120 | @export(__ashrdi3, .{ .name = "__ashrdi3", .linkage = linkage }); | ||
| 121 | const __ashrti3 = @import("compiler_rt/shift.zig").__ashrti3; | ||
| 122 | @export(__ashrti3, .{ .name = "__ashrti3", .linkage = linkage }); | ||
| 123 | const __lshrdi3 = @import("compiler_rt/shift.zig").__lshrdi3; | ||
| 124 | @export(__lshrdi3, .{ .name = "__lshrdi3", .linkage = linkage }); | ||
| 125 | const __lshrti3 = @import("compiler_rt/shift.zig").__lshrti3; | ||
| 126 | @export(__lshrti3, .{ .name = "__lshrti3", .linkage = linkage }); | ||
| 127 | |||
| 128 | const __floatsidf = @import("compiler_rt/floatsiXf.zig").__floatsidf; | ||
| 129 | @export(__floatsidf, .{ .name = "__floatsidf", .linkage = linkage }); | ||
| 130 | const __floatsisf = @import("compiler_rt/floatsiXf.zig").__floatsisf; | ||
| 131 | @export(__floatsisf, .{ .name = "__floatsisf", .linkage = linkage }); | ||
| 132 | const __floatdidf = @import("compiler_rt/floatdidf.zig").__floatdidf; | ||
| 133 | @export(__floatdidf, .{ .name = "__floatdidf", .linkage = linkage }); | ||
| 134 | const __floatsitf = @import("compiler_rt/floatsiXf.zig").__floatsitf; | ||
| 135 | @export(__floatsitf, .{ .name = "__floatsitf", .linkage = linkage }); | ||
| 136 | |||
| 137 | const __floatunsisf = @import("compiler_rt/floatunsisf.zig").__floatunsisf; | ||
| 138 | @export(__floatunsisf, .{ .name = "__floatunsisf", .linkage = linkage }); | ||
| 139 | const __floatundisf = @import("compiler_rt/floatundisf.zig").__floatundisf; | ||
| 140 | @export(__floatundisf, .{ .name = "__floatundisf", .linkage = linkage }); | ||
| 141 | const __floatunsidf = @import("compiler_rt/floatunsidf.zig").__floatunsidf; | ||
| 142 | @export(__floatunsidf, .{ .name = "__floatunsidf", .linkage = linkage }); | ||
| 143 | const __floatundidf = @import("compiler_rt/floatundidf.zig").__floatundidf; | ||
| 144 | @export(__floatundidf, .{ .name = "__floatundidf", .linkage = linkage }); | ||
| 145 | |||
| 146 | const __floatditf = @import("compiler_rt/floatditf.zig").__floatditf; | ||
| 147 | @export(__floatditf, .{ .name = "__floatditf", .linkage = linkage }); | ||
| 148 | const __floattitf = @import("compiler_rt/floattitf.zig").__floattitf; | ||
| 149 | @export(__floattitf, .{ .name = "__floattitf", .linkage = linkage }); | ||
| 150 | const __floattidf = @import("compiler_rt/floattidf.zig").__floattidf; | ||
| 151 | @export(__floattidf, .{ .name = "__floattidf", .linkage = linkage }); | ||
| 152 | const __floattisf = @import("compiler_rt/floatXisf.zig").__floattisf; | ||
| 153 | @export(__floattisf, .{ .name = "__floattisf", .linkage = linkage }); | ||
| 154 | const __floatdisf = @import("compiler_rt/floatXisf.zig").__floatdisf; | ||
| 155 | @export(__floatdisf, .{ .name = "__floatdisf", .linkage = linkage }); | ||
| 156 | |||
| 157 | const __floatunditf = @import("compiler_rt/floatunditf.zig").__floatunditf; | ||
| 158 | @export(__floatunditf, .{ .name = "__floatunditf", .linkage = linkage }); | ||
| 159 | const __floatunsitf = @import("compiler_rt/floatunsitf.zig").__floatunsitf; | ||
| 160 | @export(__floatunsitf, .{ .name = "__floatunsitf", .linkage = linkage }); | ||
| 161 | |||
| 162 | const __floatuntitf = @import("compiler_rt/floatuntitf.zig").__floatuntitf; | ||
| 163 | @export(__floatuntitf, .{ .name = "__floatuntitf", .linkage = linkage }); | ||
| 164 | const __floatuntidf = @import("compiler_rt/floatuntidf.zig").__floatuntidf; | ||
| 165 | @export(__floatuntidf, .{ .name = "__floatuntidf", .linkage = linkage }); | ||
| 166 | const __floatuntisf = @import("compiler_rt/floatuntisf.zig").__floatuntisf; | ||
| 167 | @export(__floatuntisf, .{ .name = "__floatuntisf", .linkage = linkage }); | ||
| 168 | 20 | ||
| 21 | comptime { | ||
| 169 | const __extenddftf2 = @import("compiler_rt/extendXfYf2.zig").__extenddftf2; | 22 | const __extenddftf2 = @import("compiler_rt/extendXfYf2.zig").__extenddftf2; |
| 170 | @export(__extenddftf2, .{ .name = "__extenddftf2", .linkage = linkage }); | 23 | @export(__extenddftf2, .{ .name = "__extenddftf2", .linkage = linkage }); |
| 171 | const __extendsftf2 = @import("compiler_rt/extendXfYf2.zig").__extendsftf2; | 24 | const __extendsftf2 = @import("compiler_rt/extendXfYf2.zig").__extendsftf2; |
| ... | @@ -175,446 +28,611 @@ comptime { | ... | @@ -175,446 +28,611 @@ comptime { |
| 175 | const __extendhftf2 = @import("compiler_rt/extendXfYf2.zig").__extendhftf2; | 28 | const __extendhftf2 = @import("compiler_rt/extendXfYf2.zig").__extendhftf2; |
| 176 | @export(__extendhftf2, .{ .name = "__extendhftf2", .linkage = linkage }); | 29 | @export(__extendhftf2, .{ .name = "__extendhftf2", .linkage = linkage }); |
| 177 | 30 | ||
| 178 | const __truncsfhf2 = @import("compiler_rt/truncXfYf2.zig").__truncsfhf2; | 31 | if (!builtin.zig_is_stage2) { |
| 179 | @export(__truncsfhf2, .{ .name = "__truncsfhf2", .linkage = linkage }); | 32 | switch (arch) { |
| 180 | const __truncdfhf2 = @import("compiler_rt/truncXfYf2.zig").__truncdfhf2; | 33 | .i386, |
| 181 | @export(__truncdfhf2, .{ .name = "__truncdfhf2", .linkage = linkage }); | 34 | .x86_64, |
| 182 | const __trunctfhf2 = @import("compiler_rt/truncXfYf2.zig").__trunctfhf2; | 35 | => { |
| 183 | @export(__trunctfhf2, .{ .name = "__trunctfhf2", .linkage = linkage }); | 36 | const zig_probe_stack = @import("compiler_rt/stack_probe.zig").zig_probe_stack; |
| 184 | const __trunctfdf2 = @import("compiler_rt/truncXfYf2.zig").__trunctfdf2; | 37 | @export(zig_probe_stack, .{ |
| 185 | @export(__trunctfdf2, .{ .name = "__trunctfdf2", .linkage = linkage }); | 38 | .name = "__zig_probe_stack", |
| 186 | const __trunctfsf2 = @import("compiler_rt/truncXfYf2.zig").__trunctfsf2; | 39 | .linkage = linkage, |
| 187 | @export(__trunctfsf2, .{ .name = "__trunctfsf2", .linkage = linkage }); | 40 | }); |
| 188 | 41 | }, | |
| 189 | const __truncdfsf2 = @import("compiler_rt/truncXfYf2.zig").__truncdfsf2; | ||
| 190 | @export(__truncdfsf2, .{ .name = "__truncdfsf2", .linkage = linkage }); | ||
| 191 | |||
| 192 | const __extendsfdf2 = @import("compiler_rt/extendXfYf2.zig").__extendsfdf2; | ||
| 193 | @export(__extendsfdf2, .{ .name = "__extendsfdf2", .linkage = linkage }); | ||
| 194 | |||
| 195 | const __fixunssfsi = @import("compiler_rt/fixunssfsi.zig").__fixunssfsi; | ||
| 196 | @export(__fixunssfsi, .{ .name = "__fixunssfsi", .linkage = linkage }); | ||
| 197 | const __fixunssfdi = @import("compiler_rt/fixunssfdi.zig").__fixunssfdi; | ||
| 198 | @export(__fixunssfdi, .{ .name = "__fixunssfdi", .linkage = linkage }); | ||
| 199 | const __fixunssfti = @import("compiler_rt/fixunssfti.zig").__fixunssfti; | ||
| 200 | @export(__fixunssfti, .{ .name = "__fixunssfti", .linkage = linkage }); | ||
| 201 | |||
| 202 | const __fixunsdfsi = @import("compiler_rt/fixunsdfsi.zig").__fixunsdfsi; | ||
| 203 | @export(__fixunsdfsi, .{ .name = "__fixunsdfsi", .linkage = linkage }); | ||
| 204 | const __fixunsdfdi = @import("compiler_rt/fixunsdfdi.zig").__fixunsdfdi; | ||
| 205 | @export(__fixunsdfdi, .{ .name = "__fixunsdfdi", .linkage = linkage }); | ||
| 206 | const __fixunsdfti = @import("compiler_rt/fixunsdfti.zig").__fixunsdfti; | ||
| 207 | @export(__fixunsdfti, .{ .name = "__fixunsdfti", .linkage = linkage }); | ||
| 208 | |||
| 209 | const __fixunstfsi = @import("compiler_rt/fixunstfsi.zig").__fixunstfsi; | ||
| 210 | @export(__fixunstfsi, .{ .name = "__fixunstfsi", .linkage = linkage }); | ||
| 211 | const __fixunstfdi = @import("compiler_rt/fixunstfdi.zig").__fixunstfdi; | ||
| 212 | @export(__fixunstfdi, .{ .name = "__fixunstfdi", .linkage = linkage }); | ||
| 213 | const __fixunstfti = @import("compiler_rt/fixunstfti.zig").__fixunstfti; | ||
| 214 | @export(__fixunstfti, .{ .name = "__fixunstfti", .linkage = linkage }); | ||
| 215 | |||
| 216 | const __fixdfdi = @import("compiler_rt/fixdfdi.zig").__fixdfdi; | ||
| 217 | @export(__fixdfdi, .{ .name = "__fixdfdi", .linkage = linkage }); | ||
| 218 | const __fixdfsi = @import("compiler_rt/fixdfsi.zig").__fixdfsi; | ||
| 219 | @export(__fixdfsi, .{ .name = "__fixdfsi", .linkage = linkage }); | ||
| 220 | const __fixdfti = @import("compiler_rt/fixdfti.zig").__fixdfti; | ||
| 221 | @export(__fixdfti, .{ .name = "__fixdfti", .linkage = linkage }); | ||
| 222 | const __fixsfdi = @import("compiler_rt/fixsfdi.zig").__fixsfdi; | ||
| 223 | @export(__fixsfdi, .{ .name = "__fixsfdi", .linkage = linkage }); | ||
| 224 | const __fixsfsi = @import("compiler_rt/fixsfsi.zig").__fixsfsi; | ||
| 225 | @export(__fixsfsi, .{ .name = "__fixsfsi", .linkage = linkage }); | ||
| 226 | const __fixsfti = @import("compiler_rt/fixsfti.zig").__fixsfti; | ||
| 227 | @export(__fixsfti, .{ .name = "__fixsfti", .linkage = linkage }); | ||
| 228 | const __fixtfdi = @import("compiler_rt/fixtfdi.zig").__fixtfdi; | ||
| 229 | @export(__fixtfdi, .{ .name = "__fixtfdi", .linkage = linkage }); | ||
| 230 | const __fixtfsi = @import("compiler_rt/fixtfsi.zig").__fixtfsi; | ||
| 231 | @export(__fixtfsi, .{ .name = "__fixtfsi", .linkage = linkage }); | ||
| 232 | const __fixtfti = @import("compiler_rt/fixtfti.zig").__fixtfti; | ||
| 233 | @export(__fixtfti, .{ .name = "__fixtfti", .linkage = linkage }); | ||
| 234 | |||
| 235 | const __udivmoddi4 = @import("compiler_rt/int.zig").__udivmoddi4; | ||
| 236 | @export(__udivmoddi4, .{ .name = "__udivmoddi4", .linkage = linkage }); | ||
| 237 | const __popcountdi2 = @import("compiler_rt/popcountdi2.zig").__popcountdi2; | ||
| 238 | @export(__popcountdi2, .{ .name = "__popcountdi2", .linkage = linkage }); | ||
| 239 | |||
| 240 | const __mulsi3 = @import("compiler_rt/int.zig").__mulsi3; | ||
| 241 | @export(__mulsi3, .{ .name = "__mulsi3", .linkage = linkage }); | ||
| 242 | const __muldi3 = @import("compiler_rt/muldi3.zig").__muldi3; | ||
| 243 | @export(__muldi3, .{ .name = "__muldi3", .linkage = linkage }); | ||
| 244 | const __divmoddi4 = @import("compiler_rt/int.zig").__divmoddi4; | ||
| 245 | @export(__divmoddi4, .{ .name = "__divmoddi4", .linkage = linkage }); | ||
| 246 | const __divsi3 = @import("compiler_rt/int.zig").__divsi3; | ||
| 247 | @export(__divsi3, .{ .name = "__divsi3", .linkage = linkage }); | ||
| 248 | const __divdi3 = @import("compiler_rt/int.zig").__divdi3; | ||
| 249 | @export(__divdi3, .{ .name = "__divdi3", .linkage = linkage }); | ||
| 250 | const __udivsi3 = @import("compiler_rt/int.zig").__udivsi3; | ||
| 251 | @export(__udivsi3, .{ .name = "__udivsi3", .linkage = linkage }); | ||
| 252 | const __udivdi3 = @import("compiler_rt/int.zig").__udivdi3; | ||
| 253 | @export(__udivdi3, .{ .name = "__udivdi3", .linkage = linkage }); | ||
| 254 | const __modsi3 = @import("compiler_rt/int.zig").__modsi3; | ||
| 255 | @export(__modsi3, .{ .name = "__modsi3", .linkage = linkage }); | ||
| 256 | const __moddi3 = @import("compiler_rt/int.zig").__moddi3; | ||
| 257 | @export(__moddi3, .{ .name = "__moddi3", .linkage = linkage }); | ||
| 258 | const __umodsi3 = @import("compiler_rt/int.zig").__umodsi3; | ||
| 259 | @export(__umodsi3, .{ .name = "__umodsi3", .linkage = linkage }); | ||
| 260 | const __umoddi3 = @import("compiler_rt/int.zig").__umoddi3; | ||
| 261 | @export(__umoddi3, .{ .name = "__umoddi3", .linkage = linkage }); | ||
| 262 | const __divmodsi4 = @import("compiler_rt/int.zig").__divmodsi4; | ||
| 263 | @export(__divmodsi4, .{ .name = "__divmodsi4", .linkage = linkage }); | ||
| 264 | const __udivmodsi4 = @import("compiler_rt/int.zig").__udivmodsi4; | ||
| 265 | @export(__udivmodsi4, .{ .name = "__udivmodsi4", .linkage = linkage }); | ||
| 266 | |||
| 267 | const __negsf2 = @import("compiler_rt/negXf2.zig").__negsf2; | ||
| 268 | @export(__negsf2, .{ .name = "__negsf2", .linkage = linkage }); | ||
| 269 | const __negdf2 = @import("compiler_rt/negXf2.zig").__negdf2; | ||
| 270 | @export(__negdf2, .{ .name = "__negdf2", .linkage = linkage }); | ||
| 271 | |||
| 272 | const __clzsi2 = @import("compiler_rt/count0bits.zig").__clzsi2; | ||
| 273 | @export(__clzsi2, .{ .name = "__clzsi2", .linkage = linkage }); | ||
| 274 | const __clzdi2 = @import("compiler_rt/count0bits.zig").__clzdi2; | ||
| 275 | @export(__clzdi2, .{ .name = "__clzdi2", .linkage = linkage }); | ||
| 276 | const __clzti2 = @import("compiler_rt/count0bits.zig").__clzti2; | ||
| 277 | @export(__clzti2, .{ .name = "__clzti2", .linkage = linkage }); | ||
| 278 | |||
| 279 | if (builtin.link_libc and os_tag == .openbsd) { | ||
| 280 | const __emutls_get_address = @import("compiler_rt/emutls.zig").__emutls_get_address; | ||
| 281 | @export(__emutls_get_address, .{ .name = "__emutls_get_address", .linkage = linkage }); | ||
| 282 | } | ||
| 283 | 42 | ||
| 284 | if ((arch.isARM() or arch.isThumb()) and !is_test) { | 43 | else => {}, |
| 285 | const __aeabi_unwind_cpp_pr0 = @import("compiler_rt/arm.zig").__aeabi_unwind_cpp_pr0; | ||
| 286 | @export(__aeabi_unwind_cpp_pr0, .{ .name = "__aeabi_unwind_cpp_pr0", .linkage = linkage }); | ||
| 287 | const __aeabi_unwind_cpp_pr1 = @import("compiler_rt/arm.zig").__aeabi_unwind_cpp_pr1; | ||
| 288 | @export(__aeabi_unwind_cpp_pr1, .{ .name = "__aeabi_unwind_cpp_pr1", .linkage = linkage }); | ||
| 289 | const __aeabi_unwind_cpp_pr2 = @import("compiler_rt/arm.zig").__aeabi_unwind_cpp_pr2; | ||
| 290 | @export(__aeabi_unwind_cpp_pr2, .{ .name = "__aeabi_unwind_cpp_pr2", .linkage = linkage }); | ||
| 291 | |||
| 292 | @export(__muldi3, .{ .name = "__aeabi_lmul", .linkage = linkage }); | ||
| 293 | |||
| 294 | const __aeabi_ldivmod = @import("compiler_rt/arm.zig").__aeabi_ldivmod; | ||
| 295 | @export(__aeabi_ldivmod, .{ .name = "__aeabi_ldivmod", .linkage = linkage }); | ||
| 296 | const __aeabi_uldivmod = @import("compiler_rt/arm.zig").__aeabi_uldivmod; | ||
| 297 | @export(__aeabi_uldivmod, .{ .name = "__aeabi_uldivmod", .linkage = linkage }); | ||
| 298 | |||
| 299 | @export(__divsi3, .{ .name = "__aeabi_idiv", .linkage = linkage }); | ||
| 300 | const __aeabi_idivmod = @import("compiler_rt/arm.zig").__aeabi_idivmod; | ||
| 301 | @export(__aeabi_idivmod, .{ .name = "__aeabi_idivmod", .linkage = linkage }); | ||
| 302 | @export(__udivsi3, .{ .name = "__aeabi_uidiv", .linkage = linkage }); | ||
| 303 | const __aeabi_uidivmod = @import("compiler_rt/arm.zig").__aeabi_uidivmod; | ||
| 304 | @export(__aeabi_uidivmod, .{ .name = "__aeabi_uidivmod", .linkage = linkage }); | ||
| 305 | |||
| 306 | const __aeabi_memcpy = @import("compiler_rt/arm.zig").__aeabi_memcpy; | ||
| 307 | @export(__aeabi_memcpy, .{ .name = "__aeabi_memcpy", .linkage = linkage }); | ||
| 308 | @export(__aeabi_memcpy, .{ .name = "__aeabi_memcpy4", .linkage = linkage }); | ||
| 309 | @export(__aeabi_memcpy, .{ .name = "__aeabi_memcpy8", .linkage = linkage }); | ||
| 310 | |||
| 311 | const __aeabi_memmove = @import("compiler_rt/arm.zig").__aeabi_memmove; | ||
| 312 | @export(__aeabi_memmove, .{ .name = "__aeabi_memmove", .linkage = linkage }); | ||
| 313 | @export(__aeabi_memmove, .{ .name = "__aeabi_memmove4", .linkage = linkage }); | ||
| 314 | @export(__aeabi_memmove, .{ .name = "__aeabi_memmove8", .linkage = linkage }); | ||
| 315 | |||
| 316 | const __aeabi_memset = @import("compiler_rt/arm.zig").__aeabi_memset; | ||
| 317 | @export(__aeabi_memset, .{ .name = "__aeabi_memset", .linkage = linkage }); | ||
| 318 | @export(__aeabi_memset, .{ .name = "__aeabi_memset4", .linkage = linkage }); | ||
| 319 | @export(__aeabi_memset, .{ .name = "__aeabi_memset8", .linkage = linkage }); | ||
| 320 | |||
| 321 | const __aeabi_memclr = @import("compiler_rt/arm.zig").__aeabi_memclr; | ||
| 322 | @export(__aeabi_memclr, .{ .name = "__aeabi_memclr", .linkage = linkage }); | ||
| 323 | @export(__aeabi_memclr, .{ .name = "__aeabi_memclr4", .linkage = linkage }); | ||
| 324 | @export(__aeabi_memclr, .{ .name = "__aeabi_memclr8", .linkage = linkage }); | ||
| 325 | |||
| 326 | if (os_tag == .linux) { | ||
| 327 | const __aeabi_read_tp = @import("compiler_rt/arm.zig").__aeabi_read_tp; | ||
| 328 | @export(__aeabi_read_tp, .{ .name = "__aeabi_read_tp", .linkage = linkage }); | ||
| 329 | } | 44 | } |
| 330 | 45 | ||
| 331 | const __aeabi_f2d = @import("compiler_rt/extendXfYf2.zig").__aeabi_f2d; | 46 | // __clear_cache manages its own logic about whether to be exported or not. |
| 332 | @export(__aeabi_f2d, .{ .name = "__aeabi_f2d", .linkage = linkage }); | 47 | _ = @import("compiler_rt/clear_cache.zig").clear_cache; |
| 333 | const __aeabi_i2d = @import("compiler_rt/floatsiXf.zig").__aeabi_i2d; | 48 | |
| 334 | @export(__aeabi_i2d, .{ .name = "__aeabi_i2d", .linkage = linkage }); | 49 | const __lesf2 = @import("compiler_rt/compareXf2.zig").__lesf2; |
| 335 | const __aeabi_l2d = @import("compiler_rt/floatdidf.zig").__aeabi_l2d; | 50 | @export(__lesf2, .{ .name = "__lesf2", .linkage = linkage }); |
| 336 | @export(__aeabi_l2d, .{ .name = "__aeabi_l2d", .linkage = linkage }); | 51 | const __ledf2 = @import("compiler_rt/compareXf2.zig").__ledf2; |
| 337 | const __aeabi_l2f = @import("compiler_rt/floatXisf.zig").__aeabi_l2f; | 52 | @export(__ledf2, .{ .name = "__ledf2", .linkage = linkage }); |
| 338 | @export(__aeabi_l2f, .{ .name = "__aeabi_l2f", .linkage = linkage }); | 53 | const __letf2 = @import("compiler_rt/compareXf2.zig").__letf2; |
| 339 | const __aeabi_ui2d = @import("compiler_rt/floatunsidf.zig").__aeabi_ui2d; | 54 | @export(__letf2, .{ .name = "__letf2", .linkage = linkage }); |
| 340 | @export(__aeabi_ui2d, .{ .name = "__aeabi_ui2d", .linkage = linkage }); | 55 | |
| 341 | const __aeabi_ul2d = @import("compiler_rt/floatundidf.zig").__aeabi_ul2d; | 56 | const __gesf2 = @import("compiler_rt/compareXf2.zig").__gesf2; |
| 342 | @export(__aeabi_ul2d, .{ .name = "__aeabi_ul2d", .linkage = linkage }); | 57 | @export(__gesf2, .{ .name = "__gesf2", .linkage = linkage }); |
| 343 | const __aeabi_ui2f = @import("compiler_rt/floatunsisf.zig").__aeabi_ui2f; | 58 | const __gedf2 = @import("compiler_rt/compareXf2.zig").__gedf2; |
| 344 | @export(__aeabi_ui2f, .{ .name = "__aeabi_ui2f", .linkage = linkage }); | 59 | @export(__gedf2, .{ .name = "__gedf2", .linkage = linkage }); |
| 345 | const __aeabi_ul2f = @import("compiler_rt/floatundisf.zig").__aeabi_ul2f; | 60 | const __getf2 = @import("compiler_rt/compareXf2.zig").__getf2; |
| 346 | @export(__aeabi_ul2f, .{ .name = "__aeabi_ul2f", .linkage = linkage }); | 61 | @export(__getf2, .{ .name = "__getf2", .linkage = linkage }); |
| 347 | 62 | ||
| 348 | const __aeabi_fneg = @import("compiler_rt/negXf2.zig").__aeabi_fneg; | 63 | if (!is_test) { |
| 349 | @export(__aeabi_fneg, .{ .name = "__aeabi_fneg", .linkage = linkage }); | 64 | @export(__lesf2, .{ .name = "__cmpsf2", .linkage = linkage }); |
| 350 | const __aeabi_dneg = @import("compiler_rt/negXf2.zig").__aeabi_dneg; | 65 | @export(__ledf2, .{ .name = "__cmpdf2", .linkage = linkage }); |
| 351 | @export(__aeabi_dneg, .{ .name = "__aeabi_dneg", .linkage = linkage }); | 66 | @export(__letf2, .{ .name = "__cmptf2", .linkage = linkage }); |
| 352 | 67 | ||
| 353 | const __aeabi_fmul = @import("compiler_rt/mulXf3.zig").__aeabi_fmul; | 68 | const __eqsf2 = @import("compiler_rt/compareXf2.zig").__eqsf2; |
| 354 | @export(__aeabi_fmul, .{ .name = "__aeabi_fmul", .linkage = linkage }); | 69 | @export(__eqsf2, .{ .name = "__eqsf2", .linkage = linkage }); |
| 355 | const __aeabi_dmul = @import("compiler_rt/mulXf3.zig").__aeabi_dmul; | 70 | const __eqdf2 = @import("compiler_rt/compareXf2.zig").__eqdf2; |
| 356 | @export(__aeabi_dmul, .{ .name = "__aeabi_dmul", .linkage = linkage }); | 71 | @export(__eqdf2, .{ .name = "__eqdf2", .linkage = linkage }); |
| 357 | 72 | @export(__letf2, .{ .name = "__eqtf2", .linkage = linkage }); | |
| 358 | const __aeabi_d2h = @import("compiler_rt/truncXfYf2.zig").__aeabi_d2h; | 73 | |
| 359 | @export(__aeabi_d2h, .{ .name = "__aeabi_d2h", .linkage = linkage }); | 74 | const __ltsf2 = @import("compiler_rt/compareXf2.zig").__ltsf2; |
| 360 | 75 | @export(__ltsf2, .{ .name = "__ltsf2", .linkage = linkage }); | |
| 361 | const __aeabi_f2ulz = @import("compiler_rt/fixunssfdi.zig").__aeabi_f2ulz; | 76 | const __ltdf2 = @import("compiler_rt/compareXf2.zig").__ltdf2; |
| 362 | @export(__aeabi_f2ulz, .{ .name = "__aeabi_f2ulz", .linkage = linkage }); | 77 | @export(__ltdf2, .{ .name = "__ltdf2", .linkage = linkage }); |
| 363 | const __aeabi_d2ulz = @import("compiler_rt/fixunsdfdi.zig").__aeabi_d2ulz; | 78 | @export(__letf2, .{ .name = "__lttf2", .linkage = linkage }); |
| 364 | @export(__aeabi_d2ulz, .{ .name = "__aeabi_d2ulz", .linkage = linkage }); | 79 | |
| 365 | 80 | const __nesf2 = @import("compiler_rt/compareXf2.zig").__nesf2; | |
| 366 | const __aeabi_f2lz = @import("compiler_rt/fixsfdi.zig").__aeabi_f2lz; | 81 | @export(__nesf2, .{ .name = "__nesf2", .linkage = linkage }); |
| 367 | @export(__aeabi_f2lz, .{ .name = "__aeabi_f2lz", .linkage = linkage }); | 82 | const __nedf2 = @import("compiler_rt/compareXf2.zig").__nedf2; |
| 368 | const __aeabi_d2lz = @import("compiler_rt/fixdfdi.zig").__aeabi_d2lz; | 83 | @export(__nedf2, .{ .name = "__nedf2", .linkage = linkage }); |
| 369 | @export(__aeabi_d2lz, .{ .name = "__aeabi_d2lz", .linkage = linkage }); | 84 | @export(__letf2, .{ .name = "__netf2", .linkage = linkage }); |
| 370 | 85 | ||
| 371 | const __aeabi_d2uiz = @import("compiler_rt/fixunsdfsi.zig").__aeabi_d2uiz; | 86 | const __gtsf2 = @import("compiler_rt/compareXf2.zig").__gtsf2; |
| 372 | @export(__aeabi_d2uiz, .{ .name = "__aeabi_d2uiz", .linkage = linkage }); | 87 | @export(__gtsf2, .{ .name = "__gtsf2", .linkage = linkage }); |
| 373 | 88 | const __gtdf2 = @import("compiler_rt/compareXf2.zig").__gtdf2; | |
| 374 | const __aeabi_h2f = @import("compiler_rt/extendXfYf2.zig").__aeabi_h2f; | 89 | @export(__gtdf2, .{ .name = "__gtdf2", .linkage = linkage }); |
| 375 | @export(__aeabi_h2f, .{ .name = "__aeabi_h2f", .linkage = linkage }); | 90 | @export(__getf2, .{ .name = "__gttf2", .linkage = linkage }); |
| 376 | const __aeabi_f2h = @import("compiler_rt/truncXfYf2.zig").__aeabi_f2h; | 91 | |
| 377 | @export(__aeabi_f2h, .{ .name = "__aeabi_f2h", .linkage = linkage }); | 92 | @export(@import("compiler_rt/extendXfYf2.zig").__extendhfsf2, .{ |
| 378 | 93 | .name = "__gnu_h2f_ieee", | |
| 379 | const __aeabi_i2f = @import("compiler_rt/floatsiXf.zig").__aeabi_i2f; | 94 | .linkage = linkage, |
| 380 | @export(__aeabi_i2f, .{ .name = "__aeabi_i2f", .linkage = linkage }); | 95 | }); |
| 381 | const __aeabi_d2f = @import("compiler_rt/truncXfYf2.zig").__aeabi_d2f; | 96 | @export(@import("compiler_rt/truncXfYf2.zig").__truncsfhf2, .{ |
| 382 | @export(__aeabi_d2f, .{ .name = "__aeabi_d2f", .linkage = linkage }); | 97 | .name = "__gnu_f2h_ieee", |
| 383 | 98 | .linkage = linkage, | |
| 384 | const __aeabi_fadd = @import("compiler_rt/addXf3.zig").__aeabi_fadd; | 99 | }); |
| 385 | @export(__aeabi_fadd, .{ .name = "__aeabi_fadd", .linkage = linkage }); | 100 | } |
| 386 | const __aeabi_dadd = @import("compiler_rt/addXf3.zig").__aeabi_dadd; | ||
| 387 | @export(__aeabi_dadd, .{ .name = "__aeabi_dadd", .linkage = linkage }); | ||
| 388 | const __aeabi_fsub = @import("compiler_rt/addXf3.zig").__aeabi_fsub; | ||
| 389 | @export(__aeabi_fsub, .{ .name = "__aeabi_fsub", .linkage = linkage }); | ||
| 390 | const __aeabi_dsub = @import("compiler_rt/addXf3.zig").__aeabi_dsub; | ||
| 391 | @export(__aeabi_dsub, .{ .name = "__aeabi_dsub", .linkage = linkage }); | ||
| 392 | |||
| 393 | const __aeabi_f2uiz = @import("compiler_rt/fixunssfsi.zig").__aeabi_f2uiz; | ||
| 394 | @export(__aeabi_f2uiz, .{ .name = "__aeabi_f2uiz", .linkage = linkage }); | ||
| 395 | |||
| 396 | const __aeabi_f2iz = @import("compiler_rt/fixsfsi.zig").__aeabi_f2iz; | ||
| 397 | @export(__aeabi_f2iz, .{ .name = "__aeabi_f2iz", .linkage = linkage }); | ||
| 398 | const __aeabi_d2iz = @import("compiler_rt/fixdfsi.zig").__aeabi_d2iz; | ||
| 399 | @export(__aeabi_d2iz, .{ .name = "__aeabi_d2iz", .linkage = linkage }); | ||
| 400 | |||
| 401 | const __aeabi_fdiv = @import("compiler_rt/divsf3.zig").__aeabi_fdiv; | ||
| 402 | @export(__aeabi_fdiv, .{ .name = "__aeabi_fdiv", .linkage = linkage }); | ||
| 403 | const __aeabi_ddiv = @import("compiler_rt/divdf3.zig").__aeabi_ddiv; | ||
| 404 | @export(__aeabi_ddiv, .{ .name = "__aeabi_ddiv", .linkage = linkage }); | ||
| 405 | |||
| 406 | const __aeabi_llsl = @import("compiler_rt/shift.zig").__aeabi_llsl; | ||
| 407 | @export(__aeabi_llsl, .{ .name = "__aeabi_llsl", .linkage = linkage }); | ||
| 408 | const __aeabi_lasr = @import("compiler_rt/shift.zig").__aeabi_lasr; | ||
| 409 | @export(__aeabi_lasr, .{ .name = "__aeabi_lasr", .linkage = linkage }); | ||
| 410 | const __aeabi_llsr = @import("compiler_rt/shift.zig").__aeabi_llsr; | ||
| 411 | @export(__aeabi_llsr, .{ .name = "__aeabi_llsr", .linkage = linkage }); | ||
| 412 | |||
| 413 | const __aeabi_fcmpeq = @import("compiler_rt/compareXf2.zig").__aeabi_fcmpeq; | ||
| 414 | @export(__aeabi_fcmpeq, .{ .name = "__aeabi_fcmpeq", .linkage = linkage }); | ||
| 415 | const __aeabi_fcmplt = @import("compiler_rt/compareXf2.zig").__aeabi_fcmplt; | ||
| 416 | @export(__aeabi_fcmplt, .{ .name = "__aeabi_fcmplt", .linkage = linkage }); | ||
| 417 | const __aeabi_fcmple = @import("compiler_rt/compareXf2.zig").__aeabi_fcmple; | ||
| 418 | @export(__aeabi_fcmple, .{ .name = "__aeabi_fcmple", .linkage = linkage }); | ||
| 419 | const __aeabi_fcmpge = @import("compiler_rt/compareXf2.zig").__aeabi_fcmpge; | ||
| 420 | @export(__aeabi_fcmpge, .{ .name = "__aeabi_fcmpge", .linkage = linkage }); | ||
| 421 | const __aeabi_fcmpgt = @import("compiler_rt/compareXf2.zig").__aeabi_fcmpgt; | ||
| 422 | @export(__aeabi_fcmpgt, .{ .name = "__aeabi_fcmpgt", .linkage = linkage }); | ||
| 423 | const __aeabi_fcmpun = @import("compiler_rt/compareXf2.zig").__aeabi_fcmpun; | ||
| 424 | @export(__aeabi_fcmpun, .{ .name = "__aeabi_fcmpun", .linkage = linkage }); | ||
| 425 | |||
| 426 | const __aeabi_dcmpeq = @import("compiler_rt/compareXf2.zig").__aeabi_dcmpeq; | ||
| 427 | @export(__aeabi_dcmpeq, .{ .name = "__aeabi_dcmpeq", .linkage = linkage }); | ||
| 428 | const __aeabi_dcmplt = @import("compiler_rt/compareXf2.zig").__aeabi_dcmplt; | ||
| 429 | @export(__aeabi_dcmplt, .{ .name = "__aeabi_dcmplt", .linkage = linkage }); | ||
| 430 | const __aeabi_dcmple = @import("compiler_rt/compareXf2.zig").__aeabi_dcmple; | ||
| 431 | @export(__aeabi_dcmple, .{ .name = "__aeabi_dcmple", .linkage = linkage }); | ||
| 432 | const __aeabi_dcmpge = @import("compiler_rt/compareXf2.zig").__aeabi_dcmpge; | ||
| 433 | @export(__aeabi_dcmpge, .{ .name = "__aeabi_dcmpge", .linkage = linkage }); | ||
| 434 | const __aeabi_dcmpgt = @import("compiler_rt/compareXf2.zig").__aeabi_dcmpgt; | ||
| 435 | @export(__aeabi_dcmpgt, .{ .name = "__aeabi_dcmpgt", .linkage = linkage }); | ||
| 436 | const __aeabi_dcmpun = @import("compiler_rt/compareXf2.zig").__aeabi_dcmpun; | ||
| 437 | @export(__aeabi_dcmpun, .{ .name = "__aeabi_dcmpun", .linkage = linkage }); | ||
| 438 | } | ||
| 439 | 101 | ||
| 440 | if (arch == .i386 and abi == .msvc) { | 102 | const __unordsf2 = @import("compiler_rt/compareXf2.zig").__unordsf2; |
| 441 | // Don't let LLVM apply the stdcall name mangling on those MSVC builtins | 103 | @export(__unordsf2, .{ .name = "__unordsf2", .linkage = linkage }); |
| 442 | const _alldiv = @import("compiler_rt/aulldiv.zig")._alldiv; | 104 | const __unorddf2 = @import("compiler_rt/compareXf2.zig").__unorddf2; |
| 443 | @export(_alldiv, .{ .name = "\x01__alldiv", .linkage = strong_linkage }); | 105 | @export(__unorddf2, .{ .name = "__unorddf2", .linkage = linkage }); |
| 444 | const _aulldiv = @import("compiler_rt/aulldiv.zig")._aulldiv; | 106 | const __unordtf2 = @import("compiler_rt/compareXf2.zig").__unordtf2; |
| 445 | @export(_aulldiv, .{ .name = "\x01__aulldiv", .linkage = strong_linkage }); | 107 | @export(__unordtf2, .{ .name = "__unordtf2", .linkage = linkage }); |
| 446 | const _allrem = @import("compiler_rt/aullrem.zig")._allrem; | 108 | |
| 447 | @export(_allrem, .{ .name = "\x01__allrem", .linkage = strong_linkage }); | 109 | const __addsf3 = @import("compiler_rt/addXf3.zig").__addsf3; |
| 448 | const _aullrem = @import("compiler_rt/aullrem.zig")._aullrem; | 110 | @export(__addsf3, .{ .name = "__addsf3", .linkage = linkage }); |
| 449 | @export(_aullrem, .{ .name = "\x01__aullrem", .linkage = strong_linkage }); | 111 | const __adddf3 = @import("compiler_rt/addXf3.zig").__adddf3; |
| 450 | } | 112 | @export(__adddf3, .{ .name = "__adddf3", .linkage = linkage }); |
| 113 | const __addtf3 = @import("compiler_rt/addXf3.zig").__addtf3; | ||
| 114 | @export(__addtf3, .{ .name = "__addtf3", .linkage = linkage }); | ||
| 115 | const __subsf3 = @import("compiler_rt/addXf3.zig").__subsf3; | ||
| 116 | @export(__subsf3, .{ .name = "__subsf3", .linkage = linkage }); | ||
| 117 | const __subdf3 = @import("compiler_rt/addXf3.zig").__subdf3; | ||
| 118 | @export(__subdf3, .{ .name = "__subdf3", .linkage = linkage }); | ||
| 119 | const __subtf3 = @import("compiler_rt/addXf3.zig").__subtf3; | ||
| 120 | @export(__subtf3, .{ .name = "__subtf3", .linkage = linkage }); | ||
| 121 | |||
| 122 | const __mulsf3 = @import("compiler_rt/mulXf3.zig").__mulsf3; | ||
| 123 | @export(__mulsf3, .{ .name = "__mulsf3", .linkage = linkage }); | ||
| 124 | const __muldf3 = @import("compiler_rt/mulXf3.zig").__muldf3; | ||
| 125 | @export(__muldf3, .{ .name = "__muldf3", .linkage = linkage }); | ||
| 126 | const __multf3 = @import("compiler_rt/mulXf3.zig").__multf3; | ||
| 127 | @export(__multf3, .{ .name = "__multf3", .linkage = linkage }); | ||
| 128 | |||
| 129 | const __divsf3 = @import("compiler_rt/divsf3.zig").__divsf3; | ||
| 130 | @export(__divsf3, .{ .name = "__divsf3", .linkage = linkage }); | ||
| 131 | const __divdf3 = @import("compiler_rt/divdf3.zig").__divdf3; | ||
| 132 | @export(__divdf3, .{ .name = "__divdf3", .linkage = linkage }); | ||
| 133 | const __divtf3 = @import("compiler_rt/divtf3.zig").__divtf3; | ||
| 134 | @export(__divtf3, .{ .name = "__divtf3", .linkage = linkage }); | ||
| 135 | |||
| 136 | const __ashldi3 = @import("compiler_rt/shift.zig").__ashldi3; | ||
| 137 | @export(__ashldi3, .{ .name = "__ashldi3", .linkage = linkage }); | ||
| 138 | const __ashlti3 = @import("compiler_rt/shift.zig").__ashlti3; | ||
| 139 | @export(__ashlti3, .{ .name = "__ashlti3", .linkage = linkage }); | ||
| 140 | const __ashrdi3 = @import("compiler_rt/shift.zig").__ashrdi3; | ||
| 141 | @export(__ashrdi3, .{ .name = "__ashrdi3", .linkage = linkage }); | ||
| 142 | const __ashrti3 = @import("compiler_rt/shift.zig").__ashrti3; | ||
| 143 | @export(__ashrti3, .{ .name = "__ashrti3", .linkage = linkage }); | ||
| 144 | const __lshrdi3 = @import("compiler_rt/shift.zig").__lshrdi3; | ||
| 145 | @export(__lshrdi3, .{ .name = "__lshrdi3", .linkage = linkage }); | ||
| 146 | const __lshrti3 = @import("compiler_rt/shift.zig").__lshrti3; | ||
| 147 | @export(__lshrti3, .{ .name = "__lshrti3", .linkage = linkage }); | ||
| 148 | |||
| 149 | const __floatsidf = @import("compiler_rt/floatsiXf.zig").__floatsidf; | ||
| 150 | @export(__floatsidf, .{ .name = "__floatsidf", .linkage = linkage }); | ||
| 151 | const __floatsisf = @import("compiler_rt/floatsiXf.zig").__floatsisf; | ||
| 152 | @export(__floatsisf, .{ .name = "__floatsisf", .linkage = linkage }); | ||
| 153 | const __floatdidf = @import("compiler_rt/floatdidf.zig").__floatdidf; | ||
| 154 | @export(__floatdidf, .{ .name = "__floatdidf", .linkage = linkage }); | ||
| 155 | const __floatsitf = @import("compiler_rt/floatsiXf.zig").__floatsitf; | ||
| 156 | @export(__floatsitf, .{ .name = "__floatsitf", .linkage = linkage }); | ||
| 157 | |||
| 158 | const __floatunsisf = @import("compiler_rt/floatunsisf.zig").__floatunsisf; | ||
| 159 | @export(__floatunsisf, .{ .name = "__floatunsisf", .linkage = linkage }); | ||
| 160 | const __floatundisf = @import("compiler_rt/floatundisf.zig").__floatundisf; | ||
| 161 | @export(__floatundisf, .{ .name = "__floatundisf", .linkage = linkage }); | ||
| 162 | const __floatunsidf = @import("compiler_rt/floatunsidf.zig").__floatunsidf; | ||
| 163 | @export(__floatunsidf, .{ .name = "__floatunsidf", .linkage = linkage }); | ||
| 164 | const __floatundidf = @import("compiler_rt/floatundidf.zig").__floatundidf; | ||
| 165 | @export(__floatundidf, .{ .name = "__floatundidf", .linkage = linkage }); | ||
| 166 | |||
| 167 | const __floatditf = @import("compiler_rt/floatditf.zig").__floatditf; | ||
| 168 | @export(__floatditf, .{ .name = "__floatditf", .linkage = linkage }); | ||
| 169 | const __floattitf = @import("compiler_rt/floattitf.zig").__floattitf; | ||
| 170 | @export(__floattitf, .{ .name = "__floattitf", .linkage = linkage }); | ||
| 171 | const __floattidf = @import("compiler_rt/floattidf.zig").__floattidf; | ||
| 172 | @export(__floattidf, .{ .name = "__floattidf", .linkage = linkage }); | ||
| 173 | const __floattisf = @import("compiler_rt/floatXisf.zig").__floattisf; | ||
| 174 | @export(__floattisf, .{ .name = "__floattisf", .linkage = linkage }); | ||
| 175 | const __floatdisf = @import("compiler_rt/floatXisf.zig").__floatdisf; | ||
| 176 | @export(__floatdisf, .{ .name = "__floatdisf", .linkage = linkage }); | ||
| 177 | |||
| 178 | const __floatunditf = @import("compiler_rt/floatunditf.zig").__floatunditf; | ||
| 179 | @export(__floatunditf, .{ .name = "__floatunditf", .linkage = linkage }); | ||
| 180 | const __floatunsitf = @import("compiler_rt/floatunsitf.zig").__floatunsitf; | ||
| 181 | @export(__floatunsitf, .{ .name = "__floatunsitf", .linkage = linkage }); | ||
| 182 | |||
| 183 | const __floatuntitf = @import("compiler_rt/floatuntitf.zig").__floatuntitf; | ||
| 184 | @export(__floatuntitf, .{ .name = "__floatuntitf", .linkage = linkage }); | ||
| 185 | const __floatuntidf = @import("compiler_rt/floatuntidf.zig").__floatuntidf; | ||
| 186 | @export(__floatuntidf, .{ .name = "__floatuntidf", .linkage = linkage }); | ||
| 187 | const __floatuntisf = @import("compiler_rt/floatuntisf.zig").__floatuntisf; | ||
| 188 | @export(__floatuntisf, .{ .name = "__floatuntisf", .linkage = linkage }); | ||
| 451 | 189 | ||
| 452 | if (arch.isSPARC()) { | 190 | const __truncsfhf2 = @import("compiler_rt/truncXfYf2.zig").__truncsfhf2; |
| 453 | // SPARC systems use a different naming scheme | 191 | @export(__truncsfhf2, .{ .name = "__truncsfhf2", .linkage = linkage }); |
| 454 | const _Qp_add = @import("compiler_rt/sparc.zig")._Qp_add; | 192 | const __truncdfhf2 = @import("compiler_rt/truncXfYf2.zig").__truncdfhf2; |
| 455 | @export(_Qp_add, .{ .name = "_Qp_add", .linkage = linkage }); | 193 | @export(__truncdfhf2, .{ .name = "__truncdfhf2", .linkage = linkage }); |
| 456 | const _Qp_div = @import("compiler_rt/sparc.zig")._Qp_div; | 194 | const __trunctfhf2 = @import("compiler_rt/truncXfYf2.zig").__trunctfhf2; |
| 457 | @export(_Qp_div, .{ .name = "_Qp_div", .linkage = linkage }); | 195 | @export(__trunctfhf2, .{ .name = "__trunctfhf2", .linkage = linkage }); |
| 458 | const _Qp_mul = @import("compiler_rt/sparc.zig")._Qp_mul; | 196 | const __trunctfdf2 = @import("compiler_rt/truncXfYf2.zig").__trunctfdf2; |
| 459 | @export(_Qp_mul, .{ .name = "_Qp_mul", .linkage = linkage }); | 197 | @export(__trunctfdf2, .{ .name = "__trunctfdf2", .linkage = linkage }); |
| 460 | const _Qp_sub = @import("compiler_rt/sparc.zig")._Qp_sub; | 198 | const __trunctfsf2 = @import("compiler_rt/truncXfYf2.zig").__trunctfsf2; |
| 461 | @export(_Qp_sub, .{ .name = "_Qp_sub", .linkage = linkage }); | 199 | @export(__trunctfsf2, .{ .name = "__trunctfsf2", .linkage = linkage }); |
| 462 | 200 | ||
| 463 | const _Qp_cmp = @import("compiler_rt/sparc.zig")._Qp_cmp; | 201 | const __truncdfsf2 = @import("compiler_rt/truncXfYf2.zig").__truncdfsf2; |
| 464 | @export(_Qp_cmp, .{ .name = "_Qp_cmp", .linkage = linkage }); | 202 | @export(__truncdfsf2, .{ .name = "__truncdfsf2", .linkage = linkage }); |
| 465 | const _Qp_feq = @import("compiler_rt/sparc.zig")._Qp_feq; | 203 | |
| 466 | @export(_Qp_feq, .{ .name = "_Qp_feq", .linkage = linkage }); | 204 | const __extendsfdf2 = @import("compiler_rt/extendXfYf2.zig").__extendsfdf2; |
| 467 | const _Qp_fne = @import("compiler_rt/sparc.zig")._Qp_fne; | 205 | @export(__extendsfdf2, .{ .name = "__extendsfdf2", .linkage = linkage }); |
| 468 | @export(_Qp_fne, .{ .name = "_Qp_fne", .linkage = linkage }); | 206 | |
| 469 | const _Qp_flt = @import("compiler_rt/sparc.zig")._Qp_flt; | 207 | const __fixunssfsi = @import("compiler_rt/fixunssfsi.zig").__fixunssfsi; |
| 470 | @export(_Qp_flt, .{ .name = "_Qp_flt", .linkage = linkage }); | 208 | @export(__fixunssfsi, .{ .name = "__fixunssfsi", .linkage = linkage }); |
| 471 | const _Qp_fle = @import("compiler_rt/sparc.zig")._Qp_fle; | 209 | const __fixunssfdi = @import("compiler_rt/fixunssfdi.zig").__fixunssfdi; |
| 472 | @export(_Qp_fle, .{ .name = "_Qp_fle", .linkage = linkage }); | 210 | @export(__fixunssfdi, .{ .name = "__fixunssfdi", .linkage = linkage }); |
| 473 | const _Qp_fgt = @import("compiler_rt/sparc.zig")._Qp_fgt; | 211 | const __fixunssfti = @import("compiler_rt/fixunssfti.zig").__fixunssfti; |
| 474 | @export(_Qp_fgt, .{ .name = "_Qp_fgt", .linkage = linkage }); | 212 | @export(__fixunssfti, .{ .name = "__fixunssfti", .linkage = linkage }); |
| 475 | const _Qp_fge = @import("compiler_rt/sparc.zig")._Qp_fge; | 213 | |
| 476 | @export(_Qp_fge, .{ .name = "_Qp_fge", .linkage = linkage }); | 214 | const __fixunsdfsi = @import("compiler_rt/fixunsdfsi.zig").__fixunsdfsi; |
| 477 | 215 | @export(__fixunsdfsi, .{ .name = "__fixunsdfsi", .linkage = linkage }); | |
| 478 | const _Qp_itoq = @import("compiler_rt/sparc.zig")._Qp_itoq; | 216 | const __fixunsdfdi = @import("compiler_rt/fixunsdfdi.zig").__fixunsdfdi; |
| 479 | @export(_Qp_itoq, .{ .name = "_Qp_itoq", .linkage = linkage }); | 217 | @export(__fixunsdfdi, .{ .name = "__fixunsdfdi", .linkage = linkage }); |
| 480 | const _Qp_uitoq = @import("compiler_rt/sparc.zig")._Qp_uitoq; | 218 | const __fixunsdfti = @import("compiler_rt/fixunsdfti.zig").__fixunsdfti; |
| 481 | @export(_Qp_uitoq, .{ .name = "_Qp_uitoq", .linkage = linkage }); | 219 | @export(__fixunsdfti, .{ .name = "__fixunsdfti", .linkage = linkage }); |
| 482 | const _Qp_xtoq = @import("compiler_rt/sparc.zig")._Qp_xtoq; | 220 | |
| 483 | @export(_Qp_xtoq, .{ .name = "_Qp_xtoq", .linkage = linkage }); | 221 | const __fixunstfsi = @import("compiler_rt/fixunstfsi.zig").__fixunstfsi; |
| 484 | const _Qp_uxtoq = @import("compiler_rt/sparc.zig")._Qp_uxtoq; | 222 | @export(__fixunstfsi, .{ .name = "__fixunstfsi", .linkage = linkage }); |
| 485 | @export(_Qp_uxtoq, .{ .name = "_Qp_uxtoq", .linkage = linkage }); | 223 | const __fixunstfdi = @import("compiler_rt/fixunstfdi.zig").__fixunstfdi; |
| 486 | const _Qp_stoq = @import("compiler_rt/sparc.zig")._Qp_stoq; | 224 | @export(__fixunstfdi, .{ .name = "__fixunstfdi", .linkage = linkage }); |
| 487 | @export(_Qp_stoq, .{ .name = "_Qp_stoq", .linkage = linkage }); | 225 | const __fixunstfti = @import("compiler_rt/fixunstfti.zig").__fixunstfti; |
| 488 | const _Qp_dtoq = @import("compiler_rt/sparc.zig")._Qp_dtoq; | 226 | @export(__fixunstfti, .{ .name = "__fixunstfti", .linkage = linkage }); |
| 489 | @export(_Qp_dtoq, .{ .name = "_Qp_dtoq", .linkage = linkage }); | 227 | |
| 490 | const _Qp_qtoi = @import("compiler_rt/sparc.zig")._Qp_qtoi; | 228 | const __fixdfdi = @import("compiler_rt/fixdfdi.zig").__fixdfdi; |
| 491 | @export(_Qp_qtoi, .{ .name = "_Qp_qtoi", .linkage = linkage }); | 229 | @export(__fixdfdi, .{ .name = "__fixdfdi", .linkage = linkage }); |
| 492 | const _Qp_qtoui = @import("compiler_rt/sparc.zig")._Qp_qtoui; | 230 | const __fixdfsi = @import("compiler_rt/fixdfsi.zig").__fixdfsi; |
| 493 | @export(_Qp_qtoui, .{ .name = "_Qp_qtoui", .linkage = linkage }); | 231 | @export(__fixdfsi, .{ .name = "__fixdfsi", .linkage = linkage }); |
| 494 | const _Qp_qtox = @import("compiler_rt/sparc.zig")._Qp_qtox; | 232 | const __fixdfti = @import("compiler_rt/fixdfti.zig").__fixdfti; |
| 495 | @export(_Qp_qtox, .{ .name = "_Qp_qtox", .linkage = linkage }); | 233 | @export(__fixdfti, .{ .name = "__fixdfti", .linkage = linkage }); |
| 496 | const _Qp_qtoux = @import("compiler_rt/sparc.zig")._Qp_qtoux; | 234 | const __fixsfdi = @import("compiler_rt/fixsfdi.zig").__fixsfdi; |
| 497 | @export(_Qp_qtoux, .{ .name = "_Qp_qtoux", .linkage = linkage }); | 235 | @export(__fixsfdi, .{ .name = "__fixsfdi", .linkage = linkage }); |
| 498 | const _Qp_qtos = @import("compiler_rt/sparc.zig")._Qp_qtos; | 236 | const __fixsfsi = @import("compiler_rt/fixsfsi.zig").__fixsfsi; |
| 499 | @export(_Qp_qtos, .{ .name = "_Qp_qtos", .linkage = linkage }); | 237 | @export(__fixsfsi, .{ .name = "__fixsfsi", .linkage = linkage }); |
| 500 | const _Qp_qtod = @import("compiler_rt/sparc.zig")._Qp_qtod; | 238 | const __fixsfti = @import("compiler_rt/fixsfti.zig").__fixsfti; |
| 501 | @export(_Qp_qtod, .{ .name = "_Qp_qtod", .linkage = linkage }); | 239 | @export(__fixsfti, .{ .name = "__fixsfti", .linkage = linkage }); |
| 502 | } | 240 | const __fixtfdi = @import("compiler_rt/fixtfdi.zig").__fixtfdi; |
| 241 | @export(__fixtfdi, .{ .name = "__fixtfdi", .linkage = linkage }); | ||
| 242 | const __fixtfsi = @import("compiler_rt/fixtfsi.zig").__fixtfsi; | ||
| 243 | @export(__fixtfsi, .{ .name = "__fixtfsi", .linkage = linkage }); | ||
| 244 | const __fixtfti = @import("compiler_rt/fixtfti.zig").__fixtfti; | ||
| 245 | @export(__fixtfti, .{ .name = "__fixtfti", .linkage = linkage }); | ||
| 246 | |||
| 247 | const __udivmoddi4 = @import("compiler_rt/int.zig").__udivmoddi4; | ||
| 248 | @export(__udivmoddi4, .{ .name = "__udivmoddi4", .linkage = linkage }); | ||
| 249 | const __popcountdi2 = @import("compiler_rt/popcountdi2.zig").__popcountdi2; | ||
| 250 | @export(__popcountdi2, .{ .name = "__popcountdi2", .linkage = linkage }); | ||
| 251 | |||
| 252 | const __mulsi3 = @import("compiler_rt/int.zig").__mulsi3; | ||
| 253 | @export(__mulsi3, .{ .name = "__mulsi3", .linkage = linkage }); | ||
| 254 | const __muldi3 = @import("compiler_rt/muldi3.zig").__muldi3; | ||
| 255 | @export(__muldi3, .{ .name = "__muldi3", .linkage = linkage }); | ||
| 256 | const __divmoddi4 = @import("compiler_rt/int.zig").__divmoddi4; | ||
| 257 | @export(__divmoddi4, .{ .name = "__divmoddi4", .linkage = linkage }); | ||
| 258 | const __divsi3 = @import("compiler_rt/int.zig").__divsi3; | ||
| 259 | @export(__divsi3, .{ .name = "__divsi3", .linkage = linkage }); | ||
| 260 | const __divdi3 = @import("compiler_rt/int.zig").__divdi3; | ||
| 261 | @export(__divdi3, .{ .name = "__divdi3", .linkage = linkage }); | ||
| 262 | const __udivsi3 = @import("compiler_rt/int.zig").__udivsi3; | ||
| 263 | @export(__udivsi3, .{ .name = "__udivsi3", .linkage = linkage }); | ||
| 264 | const __udivdi3 = @import("compiler_rt/int.zig").__udivdi3; | ||
| 265 | @export(__udivdi3, .{ .name = "__udivdi3", .linkage = linkage }); | ||
| 266 | const __modsi3 = @import("compiler_rt/int.zig").__modsi3; | ||
| 267 | @export(__modsi3, .{ .name = "__modsi3", .linkage = linkage }); | ||
| 268 | const __moddi3 = @import("compiler_rt/int.zig").__moddi3; | ||
| 269 | @export(__moddi3, .{ .name = "__moddi3", .linkage = linkage }); | ||
| 270 | const __umodsi3 = @import("compiler_rt/int.zig").__umodsi3; | ||
| 271 | @export(__umodsi3, .{ .name = "__umodsi3", .linkage = linkage }); | ||
| 272 | const __umoddi3 = @import("compiler_rt/int.zig").__umoddi3; | ||
| 273 | @export(__umoddi3, .{ .name = "__umoddi3", .linkage = linkage }); | ||
| 274 | const __divmodsi4 = @import("compiler_rt/int.zig").__divmodsi4; | ||
| 275 | @export(__divmodsi4, .{ .name = "__divmodsi4", .linkage = linkage }); | ||
| 276 | const __udivmodsi4 = @import("compiler_rt/int.zig").__udivmodsi4; | ||
| 277 | @export(__udivmodsi4, .{ .name = "__udivmodsi4", .linkage = linkage }); | ||
| 278 | |||
| 279 | const __negsf2 = @import("compiler_rt/negXf2.zig").__negsf2; | ||
| 280 | @export(__negsf2, .{ .name = "__negsf2", .linkage = linkage }); | ||
| 281 | const __negdf2 = @import("compiler_rt/negXf2.zig").__negdf2; | ||
| 282 | @export(__negdf2, .{ .name = "__negdf2", .linkage = linkage }); | ||
| 283 | |||
| 284 | const __clzsi2 = @import("compiler_rt/count0bits.zig").__clzsi2; | ||
| 285 | @export(__clzsi2, .{ .name = "__clzsi2", .linkage = linkage }); | ||
| 286 | const __clzdi2 = @import("compiler_rt/count0bits.zig").__clzdi2; | ||
| 287 | @export(__clzdi2, .{ .name = "__clzdi2", .linkage = linkage }); | ||
| 288 | const __clzti2 = @import("compiler_rt/count0bits.zig").__clzti2; | ||
| 289 | @export(__clzti2, .{ .name = "__clzti2", .linkage = linkage }); | ||
| 290 | |||
| 291 | if (builtin.link_libc and os_tag == .openbsd) { | ||
| 292 | const __emutls_get_address = @import("compiler_rt/emutls.zig").__emutls_get_address; | ||
| 293 | @export(__emutls_get_address, .{ .name = "__emutls_get_address", .linkage = linkage }); | ||
| 294 | } | ||
| 503 | 295 | ||
| 504 | if ((arch == .powerpc or arch.isPPC64()) and !is_test) { | 296 | if ((arch.isARM() or arch.isThumb()) and !is_test) { |
| 505 | @export(__addtf3, .{ .name = "__addkf3", .linkage = linkage }); | 297 | const __aeabi_unwind_cpp_pr0 = @import("compiler_rt/arm.zig").__aeabi_unwind_cpp_pr0; |
| 506 | @export(__subtf3, .{ .name = "__subkf3", .linkage = linkage }); | 298 | @export(__aeabi_unwind_cpp_pr0, .{ .name = "__aeabi_unwind_cpp_pr0", .linkage = linkage }); |
| 507 | @export(__multf3, .{ .name = "__mulkf3", .linkage = linkage }); | 299 | const __aeabi_unwind_cpp_pr1 = @import("compiler_rt/arm.zig").__aeabi_unwind_cpp_pr1; |
| 508 | @export(__divtf3, .{ .name = "__divkf3", .linkage = linkage }); | 300 | @export(__aeabi_unwind_cpp_pr1, .{ .name = "__aeabi_unwind_cpp_pr1", .linkage = linkage }); |
| 509 | @export(__extendsftf2, .{ .name = "__extendsfkf2", .linkage = linkage }); | 301 | const __aeabi_unwind_cpp_pr2 = @import("compiler_rt/arm.zig").__aeabi_unwind_cpp_pr2; |
| 510 | @export(__extenddftf2, .{ .name = "__extenddfkf2", .linkage = linkage }); | 302 | @export(__aeabi_unwind_cpp_pr2, .{ .name = "__aeabi_unwind_cpp_pr2", .linkage = linkage }); |
| 511 | @export(__trunctfsf2, .{ .name = "__trunckfsf2", .linkage = linkage }); | 303 | |
| 512 | @export(__trunctfdf2, .{ .name = "__trunckfdf2", .linkage = linkage }); | 304 | @export(__muldi3, .{ .name = "__aeabi_lmul", .linkage = linkage }); |
| 513 | @export(__fixtfdi, .{ .name = "__fixkfdi", .linkage = linkage }); | 305 | |
| 514 | @export(__fixtfsi, .{ .name = "__fixkfsi", .linkage = linkage }); | 306 | const __aeabi_ldivmod = @import("compiler_rt/arm.zig").__aeabi_ldivmod; |
| 515 | @export(__fixunstfsi, .{ .name = "__fixunskfsi", .linkage = linkage }); | 307 | @export(__aeabi_ldivmod, .{ .name = "__aeabi_ldivmod", .linkage = linkage }); |
| 516 | @export(__fixunstfdi, .{ .name = "__fixunskfdi", .linkage = linkage }); | 308 | const __aeabi_uldivmod = @import("compiler_rt/arm.zig").__aeabi_uldivmod; |
| 517 | @export(__floatsitf, .{ .name = "__floatsikf", .linkage = linkage }); | 309 | @export(__aeabi_uldivmod, .{ .name = "__aeabi_uldivmod", .linkage = linkage }); |
| 518 | @export(__floatditf, .{ .name = "__floatdikf", .linkage = linkage }); | 310 | |
| 519 | @export(__floatunditf, .{ .name = "__floatundikf", .linkage = linkage }); | 311 | @export(__divsi3, .{ .name = "__aeabi_idiv", .linkage = linkage }); |
| 520 | @export(__floatunsitf, .{ .name = "__floatunsikf", .linkage = linkage }); | 312 | const __aeabi_idivmod = @import("compiler_rt/arm.zig").__aeabi_idivmod; |
| 521 | 313 | @export(__aeabi_idivmod, .{ .name = "__aeabi_idivmod", .linkage = linkage }); | |
| 522 | @export(__letf2, .{ .name = "__eqkf2", .linkage = linkage }); | 314 | @export(__udivsi3, .{ .name = "__aeabi_uidiv", .linkage = linkage }); |
| 523 | @export(__letf2, .{ .name = "__nekf2", .linkage = linkage }); | 315 | const __aeabi_uidivmod = @import("compiler_rt/arm.zig").__aeabi_uidivmod; |
| 524 | @export(__getf2, .{ .name = "__gekf2", .linkage = linkage }); | 316 | @export(__aeabi_uidivmod, .{ .name = "__aeabi_uidivmod", .linkage = linkage }); |
| 525 | @export(__letf2, .{ .name = "__ltkf2", .linkage = linkage }); | 317 | |
| 526 | @export(__letf2, .{ .name = "__lekf2", .linkage = linkage }); | 318 | const __aeabi_memcpy = @import("compiler_rt/arm.zig").__aeabi_memcpy; |
| 527 | @export(__getf2, .{ .name = "__gtkf2", .linkage = linkage }); | 319 | @export(__aeabi_memcpy, .{ .name = "__aeabi_memcpy", .linkage = linkage }); |
| 528 | @export(__unordtf2, .{ .name = "__unordkf2", .linkage = linkage }); | 320 | @export(__aeabi_memcpy, .{ .name = "__aeabi_memcpy4", .linkage = linkage }); |
| 529 | } | 321 | @export(__aeabi_memcpy, .{ .name = "__aeabi_memcpy8", .linkage = linkage }); |
| 322 | |||
| 323 | const __aeabi_memmove = @import("compiler_rt/arm.zig").__aeabi_memmove; | ||
| 324 | @export(__aeabi_memmove, .{ .name = "__aeabi_memmove", .linkage = linkage }); | ||
| 325 | @export(__aeabi_memmove, .{ .name = "__aeabi_memmove4", .linkage = linkage }); | ||
| 326 | @export(__aeabi_memmove, .{ .name = "__aeabi_memmove8", .linkage = linkage }); | ||
| 327 | |||
| 328 | const __aeabi_memset = @import("compiler_rt/arm.zig").__aeabi_memset; | ||
| 329 | @export(__aeabi_memset, .{ .name = "__aeabi_memset", .linkage = linkage }); | ||
| 330 | @export(__aeabi_memset, .{ .name = "__aeabi_memset4", .linkage = linkage }); | ||
| 331 | @export(__aeabi_memset, .{ .name = "__aeabi_memset8", .linkage = linkage }); | ||
| 332 | |||
| 333 | const __aeabi_memclr = @import("compiler_rt/arm.zig").__aeabi_memclr; | ||
| 334 | @export(__aeabi_memclr, .{ .name = "__aeabi_memclr", .linkage = linkage }); | ||
| 335 | @export(__aeabi_memclr, .{ .name = "__aeabi_memclr4", .linkage = linkage }); | ||
| 336 | @export(__aeabi_memclr, .{ .name = "__aeabi_memclr8", .linkage = linkage }); | ||
| 337 | |||
| 338 | if (os_tag == .linux) { | ||
| 339 | const __aeabi_read_tp = @import("compiler_rt/arm.zig").__aeabi_read_tp; | ||
| 340 | @export(__aeabi_read_tp, .{ .name = "__aeabi_read_tp", .linkage = linkage }); | ||
| 341 | } | ||
| 342 | |||
| 343 | const __aeabi_f2d = @import("compiler_rt/extendXfYf2.zig").__aeabi_f2d; | ||
| 344 | @export(__aeabi_f2d, .{ .name = "__aeabi_f2d", .linkage = linkage }); | ||
| 345 | const __aeabi_i2d = @import("compiler_rt/floatsiXf.zig").__aeabi_i2d; | ||
| 346 | @export(__aeabi_i2d, .{ .name = "__aeabi_i2d", .linkage = linkage }); | ||
| 347 | const __aeabi_l2d = @import("compiler_rt/floatdidf.zig").__aeabi_l2d; | ||
| 348 | @export(__aeabi_l2d, .{ .name = "__aeabi_l2d", .linkage = linkage }); | ||
| 349 | const __aeabi_l2f = @import("compiler_rt/floatXisf.zig").__aeabi_l2f; | ||
| 350 | @export(__aeabi_l2f, .{ .name = "__aeabi_l2f", .linkage = linkage }); | ||
| 351 | const __aeabi_ui2d = @import("compiler_rt/floatunsidf.zig").__aeabi_ui2d; | ||
| 352 | @export(__aeabi_ui2d, .{ .name = "__aeabi_ui2d", .linkage = linkage }); | ||
| 353 | const __aeabi_ul2d = @import("compiler_rt/floatundidf.zig").__aeabi_ul2d; | ||
| 354 | @export(__aeabi_ul2d, .{ .name = "__aeabi_ul2d", .linkage = linkage }); | ||
| 355 | const __aeabi_ui2f = @import("compiler_rt/floatunsisf.zig").__aeabi_ui2f; | ||
| 356 | @export(__aeabi_ui2f, .{ .name = "__aeabi_ui2f", .linkage = linkage }); | ||
| 357 | const __aeabi_ul2f = @import("compiler_rt/floatundisf.zig").__aeabi_ul2f; | ||
| 358 | @export(__aeabi_ul2f, .{ .name = "__aeabi_ul2f", .linkage = linkage }); | ||
| 359 | |||
| 360 | const __aeabi_fneg = @import("compiler_rt/negXf2.zig").__aeabi_fneg; | ||
| 361 | @export(__aeabi_fneg, .{ .name = "__aeabi_fneg", .linkage = linkage }); | ||
| 362 | const __aeabi_dneg = @import("compiler_rt/negXf2.zig").__aeabi_dneg; | ||
| 363 | @export(__aeabi_dneg, .{ .name = "__aeabi_dneg", .linkage = linkage }); | ||
| 364 | |||
| 365 | const __aeabi_fmul = @import("compiler_rt/mulXf3.zig").__aeabi_fmul; | ||
| 366 | @export(__aeabi_fmul, .{ .name = "__aeabi_fmul", .linkage = linkage }); | ||
| 367 | const __aeabi_dmul = @import("compiler_rt/mulXf3.zig").__aeabi_dmul; | ||
| 368 | @export(__aeabi_dmul, .{ .name = "__aeabi_dmul", .linkage = linkage }); | ||
| 369 | |||
| 370 | const __aeabi_d2h = @import("compiler_rt/truncXfYf2.zig").__aeabi_d2h; | ||
| 371 | @export(__aeabi_d2h, .{ .name = "__aeabi_d2h", .linkage = linkage }); | ||
| 372 | |||
| 373 | const __aeabi_f2ulz = @import("compiler_rt/fixunssfdi.zig").__aeabi_f2ulz; | ||
| 374 | @export(__aeabi_f2ulz, .{ .name = "__aeabi_f2ulz", .linkage = linkage }); | ||
| 375 | const __aeabi_d2ulz = @import("compiler_rt/fixunsdfdi.zig").__aeabi_d2ulz; | ||
| 376 | @export(__aeabi_d2ulz, .{ .name = "__aeabi_d2ulz", .linkage = linkage }); | ||
| 377 | |||
| 378 | const __aeabi_f2lz = @import("compiler_rt/fixsfdi.zig").__aeabi_f2lz; | ||
| 379 | @export(__aeabi_f2lz, .{ .name = "__aeabi_f2lz", .linkage = linkage }); | ||
| 380 | const __aeabi_d2lz = @import("compiler_rt/fixdfdi.zig").__aeabi_d2lz; | ||
| 381 | @export(__aeabi_d2lz, .{ .name = "__aeabi_d2lz", .linkage = linkage }); | ||
| 382 | |||
| 383 | const __aeabi_d2uiz = @import("compiler_rt/fixunsdfsi.zig").__aeabi_d2uiz; | ||
| 384 | @export(__aeabi_d2uiz, .{ .name = "__aeabi_d2uiz", .linkage = linkage }); | ||
| 385 | |||
| 386 | const __aeabi_h2f = @import("compiler_rt/extendXfYf2.zig").__aeabi_h2f; | ||
| 387 | @export(__aeabi_h2f, .{ .name = "__aeabi_h2f", .linkage = linkage }); | ||
| 388 | const __aeabi_f2h = @import("compiler_rt/truncXfYf2.zig").__aeabi_f2h; | ||
| 389 | @export(__aeabi_f2h, .{ .name = "__aeabi_f2h", .linkage = linkage }); | ||
| 390 | |||
| 391 | const __aeabi_i2f = @import("compiler_rt/floatsiXf.zig").__aeabi_i2f; | ||
| 392 | @export(__aeabi_i2f, .{ .name = "__aeabi_i2f", .linkage = linkage }); | ||
| 393 | const __aeabi_d2f = @import("compiler_rt/truncXfYf2.zig").__aeabi_d2f; | ||
| 394 | @export(__aeabi_d2f, .{ .name = "__aeabi_d2f", .linkage = linkage }); | ||
| 395 | |||
| 396 | const __aeabi_fadd = @import("compiler_rt/addXf3.zig").__aeabi_fadd; | ||
| 397 | @export(__aeabi_fadd, .{ .name = "__aeabi_fadd", .linkage = linkage }); | ||
| 398 | const __aeabi_dadd = @import("compiler_rt/addXf3.zig").__aeabi_dadd; | ||
| 399 | @export(__aeabi_dadd, .{ .name = "__aeabi_dadd", .linkage = linkage }); | ||
| 400 | const __aeabi_fsub = @import("compiler_rt/addXf3.zig").__aeabi_fsub; | ||
| 401 | @export(__aeabi_fsub, .{ .name = "__aeabi_fsub", .linkage = linkage }); | ||
| 402 | const __aeabi_dsub = @import("compiler_rt/addXf3.zig").__aeabi_dsub; | ||
| 403 | @export(__aeabi_dsub, .{ .name = "__aeabi_dsub", .linkage = linkage }); | ||
| 404 | |||
| 405 | const __aeabi_f2uiz = @import("compiler_rt/fixunssfsi.zig").__aeabi_f2uiz; | ||
| 406 | @export(__aeabi_f2uiz, .{ .name = "__aeabi_f2uiz", .linkage = linkage }); | ||
| 407 | |||
| 408 | const __aeabi_f2iz = @import("compiler_rt/fixsfsi.zig").__aeabi_f2iz; | ||
| 409 | @export(__aeabi_f2iz, .{ .name = "__aeabi_f2iz", .linkage = linkage }); | ||
| 410 | const __aeabi_d2iz = @import("compiler_rt/fixdfsi.zig").__aeabi_d2iz; | ||
| 411 | @export(__aeabi_d2iz, .{ .name = "__aeabi_d2iz", .linkage = linkage }); | ||
| 412 | |||
| 413 | const __aeabi_fdiv = @import("compiler_rt/divsf3.zig").__aeabi_fdiv; | ||
| 414 | @export(__aeabi_fdiv, .{ .name = "__aeabi_fdiv", .linkage = linkage }); | ||
| 415 | const __aeabi_ddiv = @import("compiler_rt/divdf3.zig").__aeabi_ddiv; | ||
| 416 | @export(__aeabi_ddiv, .{ .name = "__aeabi_ddiv", .linkage = linkage }); | ||
| 417 | |||
| 418 | const __aeabi_llsl = @import("compiler_rt/shift.zig").__aeabi_llsl; | ||
| 419 | @export(__aeabi_llsl, .{ .name = "__aeabi_llsl", .linkage = linkage }); | ||
| 420 | const __aeabi_lasr = @import("compiler_rt/shift.zig").__aeabi_lasr; | ||
| 421 | @export(__aeabi_lasr, .{ .name = "__aeabi_lasr", .linkage = linkage }); | ||
| 422 | const __aeabi_llsr = @import("compiler_rt/shift.zig").__aeabi_llsr; | ||
| 423 | @export(__aeabi_llsr, .{ .name = "__aeabi_llsr", .linkage = linkage }); | ||
| 424 | |||
| 425 | const __aeabi_fcmpeq = @import("compiler_rt/compareXf2.zig").__aeabi_fcmpeq; | ||
| 426 | @export(__aeabi_fcmpeq, .{ .name = "__aeabi_fcmpeq", .linkage = linkage }); | ||
| 427 | const __aeabi_fcmplt = @import("compiler_rt/compareXf2.zig").__aeabi_fcmplt; | ||
| 428 | @export(__aeabi_fcmplt, .{ .name = "__aeabi_fcmplt", .linkage = linkage }); | ||
| 429 | const __aeabi_fcmple = @import("compiler_rt/compareXf2.zig").__aeabi_fcmple; | ||
| 430 | @export(__aeabi_fcmple, .{ .name = "__aeabi_fcmple", .linkage = linkage }); | ||
| 431 | const __aeabi_fcmpge = @import("compiler_rt/compareXf2.zig").__aeabi_fcmpge; | ||
| 432 | @export(__aeabi_fcmpge, .{ .name = "__aeabi_fcmpge", .linkage = linkage }); | ||
| 433 | const __aeabi_fcmpgt = @import("compiler_rt/compareXf2.zig").__aeabi_fcmpgt; | ||
| 434 | @export(__aeabi_fcmpgt, .{ .name = "__aeabi_fcmpgt", .linkage = linkage }); | ||
| 435 | const __aeabi_fcmpun = @import("compiler_rt/compareXf2.zig").__aeabi_fcmpun; | ||
| 436 | @export(__aeabi_fcmpun, .{ .name = "__aeabi_fcmpun", .linkage = linkage }); | ||
| 437 | |||
| 438 | const __aeabi_dcmpeq = @import("compiler_rt/compareXf2.zig").__aeabi_dcmpeq; | ||
| 439 | @export(__aeabi_dcmpeq, .{ .name = "__aeabi_dcmpeq", .linkage = linkage }); | ||
| 440 | const __aeabi_dcmplt = @import("compiler_rt/compareXf2.zig").__aeabi_dcmplt; | ||
| 441 | @export(__aeabi_dcmplt, .{ .name = "__aeabi_dcmplt", .linkage = linkage }); | ||
| 442 | const __aeabi_dcmple = @import("compiler_rt/compareXf2.zig").__aeabi_dcmple; | ||
| 443 | @export(__aeabi_dcmple, .{ .name = "__aeabi_dcmple", .linkage = linkage }); | ||
| 444 | const __aeabi_dcmpge = @import("compiler_rt/compareXf2.zig").__aeabi_dcmpge; | ||
| 445 | @export(__aeabi_dcmpge, .{ .name = "__aeabi_dcmpge", .linkage = linkage }); | ||
| 446 | const __aeabi_dcmpgt = @import("compiler_rt/compareXf2.zig").__aeabi_dcmpgt; | ||
| 447 | @export(__aeabi_dcmpgt, .{ .name = "__aeabi_dcmpgt", .linkage = linkage }); | ||
| 448 | const __aeabi_dcmpun = @import("compiler_rt/compareXf2.zig").__aeabi_dcmpun; | ||
| 449 | @export(__aeabi_dcmpun, .{ .name = "__aeabi_dcmpun", .linkage = linkage }); | ||
| 450 | } | ||
| 530 | 451 | ||
| 531 | if (builtin.os.tag == .windows) { | 452 | if (arch == .i386 and abi == .msvc) { |
| 532 | // Default stack-probe functions emitted by LLVM | 453 | // Don't let LLVM apply the stdcall name mangling on those MSVC builtins |
| 533 | if (is_mingw) { | 454 | const _alldiv = @import("compiler_rt/aulldiv.zig")._alldiv; |
| 534 | const _chkstk = @import("compiler_rt/stack_probe.zig")._chkstk; | 455 | @export(_alldiv, .{ .name = "\x01__alldiv", .linkage = strong_linkage }); |
| 535 | @export(_chkstk, .{ .name = "_alloca", .linkage = strong_linkage }); | 456 | const _aulldiv = @import("compiler_rt/aulldiv.zig")._aulldiv; |
| 536 | const ___chkstk_ms = @import("compiler_rt/stack_probe.zig").___chkstk_ms; | 457 | @export(_aulldiv, .{ .name = "\x01__aulldiv", .linkage = strong_linkage }); |
| 537 | @export(___chkstk_ms, .{ .name = "___chkstk_ms", .linkage = strong_linkage }); | 458 | const _allrem = @import("compiler_rt/aullrem.zig")._allrem; |
| 538 | } else if (!builtin.link_libc) { | 459 | @export(_allrem, .{ .name = "\x01__allrem", .linkage = strong_linkage }); |
| 539 | // This symbols are otherwise exported by MSVCRT.lib | 460 | const _aullrem = @import("compiler_rt/aullrem.zig")._aullrem; |
| 540 | const _chkstk = @import("compiler_rt/stack_probe.zig")._chkstk; | 461 | @export(_aullrem, .{ .name = "\x01__aullrem", .linkage = strong_linkage }); |
| 541 | @export(_chkstk, .{ .name = "_chkstk", .linkage = strong_linkage }); | ||
| 542 | const __chkstk = @import("compiler_rt/stack_probe.zig").__chkstk; | ||
| 543 | @export(__chkstk, .{ .name = "__chkstk", .linkage = strong_linkage }); | ||
| 544 | } | 462 | } |
| 545 | 463 | ||
| 546 | switch (arch) { | 464 | if (arch.isSPARC()) { |
| 547 | .i386 => { | 465 | // SPARC systems use a different naming scheme |
| 548 | const __divti3 = @import("compiler_rt/divti3.zig").__divti3; | 466 | const _Qp_add = @import("compiler_rt/sparc.zig")._Qp_add; |
| 549 | @export(__divti3, .{ .name = "__divti3", .linkage = linkage }); | 467 | @export(_Qp_add, .{ .name = "_Qp_add", .linkage = linkage }); |
| 468 | const _Qp_div = @import("compiler_rt/sparc.zig")._Qp_div; | ||
| 469 | @export(_Qp_div, .{ .name = "_Qp_div", .linkage = linkage }); | ||
| 470 | const _Qp_mul = @import("compiler_rt/sparc.zig")._Qp_mul; | ||
| 471 | @export(_Qp_mul, .{ .name = "_Qp_mul", .linkage = linkage }); | ||
| 472 | const _Qp_sub = @import("compiler_rt/sparc.zig")._Qp_sub; | ||
| 473 | @export(_Qp_sub, .{ .name = "_Qp_sub", .linkage = linkage }); | ||
| 474 | |||
| 475 | const _Qp_cmp = @import("compiler_rt/sparc.zig")._Qp_cmp; | ||
| 476 | @export(_Qp_cmp, .{ .name = "_Qp_cmp", .linkage = linkage }); | ||
| 477 | const _Qp_feq = @import("compiler_rt/sparc.zig")._Qp_feq; | ||
| 478 | @export(_Qp_feq, .{ .name = "_Qp_feq", .linkage = linkage }); | ||
| 479 | const _Qp_fne = @import("compiler_rt/sparc.zig")._Qp_fne; | ||
| 480 | @export(_Qp_fne, .{ .name = "_Qp_fne", .linkage = linkage }); | ||
| 481 | const _Qp_flt = @import("compiler_rt/sparc.zig")._Qp_flt; | ||
| 482 | @export(_Qp_flt, .{ .name = "_Qp_flt", .linkage = linkage }); | ||
| 483 | const _Qp_fle = @import("compiler_rt/sparc.zig")._Qp_fle; | ||
| 484 | @export(_Qp_fle, .{ .name = "_Qp_fle", .linkage = linkage }); | ||
| 485 | const _Qp_fgt = @import("compiler_rt/sparc.zig")._Qp_fgt; | ||
| 486 | @export(_Qp_fgt, .{ .name = "_Qp_fgt", .linkage = linkage }); | ||
| 487 | const _Qp_fge = @import("compiler_rt/sparc.zig")._Qp_fge; | ||
| 488 | @export(_Qp_fge, .{ .name = "_Qp_fge", .linkage = linkage }); | ||
| 489 | |||
| 490 | const _Qp_itoq = @import("compiler_rt/sparc.zig")._Qp_itoq; | ||
| 491 | @export(_Qp_itoq, .{ .name = "_Qp_itoq", .linkage = linkage }); | ||
| 492 | const _Qp_uitoq = @import("compiler_rt/sparc.zig")._Qp_uitoq; | ||
| 493 | @export(_Qp_uitoq, .{ .name = "_Qp_uitoq", .linkage = linkage }); | ||
| 494 | const _Qp_xtoq = @import("compiler_rt/sparc.zig")._Qp_xtoq; | ||
| 495 | @export(_Qp_xtoq, .{ .name = "_Qp_xtoq", .linkage = linkage }); | ||
| 496 | const _Qp_uxtoq = @import("compiler_rt/sparc.zig")._Qp_uxtoq; | ||
| 497 | @export(_Qp_uxtoq, .{ .name = "_Qp_uxtoq", .linkage = linkage }); | ||
| 498 | const _Qp_stoq = @import("compiler_rt/sparc.zig")._Qp_stoq; | ||
| 499 | @export(_Qp_stoq, .{ .name = "_Qp_stoq", .linkage = linkage }); | ||
| 500 | const _Qp_dtoq = @import("compiler_rt/sparc.zig")._Qp_dtoq; | ||
| 501 | @export(_Qp_dtoq, .{ .name = "_Qp_dtoq", .linkage = linkage }); | ||
| 502 | const _Qp_qtoi = @import("compiler_rt/sparc.zig")._Qp_qtoi; | ||
| 503 | @export(_Qp_qtoi, .{ .name = "_Qp_qtoi", .linkage = linkage }); | ||
| 504 | const _Qp_qtoui = @import("compiler_rt/sparc.zig")._Qp_qtoui; | ||
| 505 | @export(_Qp_qtoui, .{ .name = "_Qp_qtoui", .linkage = linkage }); | ||
| 506 | const _Qp_qtox = @import("compiler_rt/sparc.zig")._Qp_qtox; | ||
| 507 | @export(_Qp_qtox, .{ .name = "_Qp_qtox", .linkage = linkage }); | ||
| 508 | const _Qp_qtoux = @import("compiler_rt/sparc.zig")._Qp_qtoux; | ||
| 509 | @export(_Qp_qtoux, .{ .name = "_Qp_qtoux", .linkage = linkage }); | ||
| 510 | const _Qp_qtos = @import("compiler_rt/sparc.zig")._Qp_qtos; | ||
| 511 | @export(_Qp_qtos, .{ .name = "_Qp_qtos", .linkage = linkage }); | ||
| 512 | const _Qp_qtod = @import("compiler_rt/sparc.zig")._Qp_qtod; | ||
| 513 | @export(_Qp_qtod, .{ .name = "_Qp_qtod", .linkage = linkage }); | ||
| 514 | } | ||
| 515 | |||
| 516 | if ((arch == .powerpc or arch.isPPC64()) and !is_test) { | ||
| 517 | @export(__addtf3, .{ .name = "__addkf3", .linkage = linkage }); | ||
| 518 | @export(__subtf3, .{ .name = "__subkf3", .linkage = linkage }); | ||
| 519 | @export(__multf3, .{ .name = "__mulkf3", .linkage = linkage }); | ||
| 520 | @export(__divtf3, .{ .name = "__divkf3", .linkage = linkage }); | ||
| 521 | @export(__extendsftf2, .{ .name = "__extendsfkf2", .linkage = linkage }); | ||
| 522 | @export(__extenddftf2, .{ .name = "__extenddfkf2", .linkage = linkage }); | ||
| 523 | @export(__trunctfsf2, .{ .name = "__trunckfsf2", .linkage = linkage }); | ||
| 524 | @export(__trunctfdf2, .{ .name = "__trunckfdf2", .linkage = linkage }); | ||
| 525 | @export(__fixtfdi, .{ .name = "__fixkfdi", .linkage = linkage }); | ||
| 526 | @export(__fixtfsi, .{ .name = "__fixkfsi", .linkage = linkage }); | ||
| 527 | @export(__fixunstfsi, .{ .name = "__fixunskfsi", .linkage = linkage }); | ||
| 528 | @export(__fixunstfdi, .{ .name = "__fixunskfdi", .linkage = linkage }); | ||
| 529 | @export(__floatsitf, .{ .name = "__floatsikf", .linkage = linkage }); | ||
| 530 | @export(__floatditf, .{ .name = "__floatdikf", .linkage = linkage }); | ||
| 531 | @export(__floatunditf, .{ .name = "__floatundikf", .linkage = linkage }); | ||
| 532 | @export(__floatunsitf, .{ .name = "__floatunsikf", .linkage = linkage }); | ||
| 533 | |||
| 534 | @export(__letf2, .{ .name = "__eqkf2", .linkage = linkage }); | ||
| 535 | @export(__letf2, .{ .name = "__nekf2", .linkage = linkage }); | ||
| 536 | @export(__getf2, .{ .name = "__gekf2", .linkage = linkage }); | ||
| 537 | @export(__letf2, .{ .name = "__ltkf2", .linkage = linkage }); | ||
| 538 | @export(__letf2, .{ .name = "__lekf2", .linkage = linkage }); | ||
| 539 | @export(__getf2, .{ .name = "__gtkf2", .linkage = linkage }); | ||
| 540 | @export(__unordtf2, .{ .name = "__unordkf2", .linkage = linkage }); | ||
| 541 | } | ||
| 542 | |||
| 543 | if (builtin.os.tag == .windows) { | ||
| 544 | // Default stack-probe functions emitted by LLVM | ||
| 545 | if (is_mingw) { | ||
| 546 | const _chkstk = @import("compiler_rt/stack_probe.zig")._chkstk; | ||
| 547 | @export(_chkstk, .{ .name = "_alloca", .linkage = strong_linkage }); | ||
| 548 | const ___chkstk_ms = @import("compiler_rt/stack_probe.zig").___chkstk_ms; | ||
| 549 | @export(___chkstk_ms, .{ .name = "___chkstk_ms", .linkage = strong_linkage }); | ||
| 550 | } else if (!builtin.link_libc) { | ||
| 551 | // This symbols are otherwise exported by MSVCRT.lib | ||
| 552 | const _chkstk = @import("compiler_rt/stack_probe.zig")._chkstk; | ||
| 553 | @export(_chkstk, .{ .name = "_chkstk", .linkage = strong_linkage }); | ||
| 554 | const __chkstk = @import("compiler_rt/stack_probe.zig").__chkstk; | ||
| 555 | @export(__chkstk, .{ .name = "__chkstk", .linkage = strong_linkage }); | ||
| 556 | } | ||
| 557 | |||
| 558 | switch (arch) { | ||
| 559 | .i386 => { | ||
| 560 | const __divti3 = @import("compiler_rt/divti3.zig").__divti3; | ||
| 561 | @export(__divti3, .{ .name = "__divti3", .linkage = linkage }); | ||
| 562 | const __modti3 = @import("compiler_rt/modti3.zig").__modti3; | ||
| 563 | @export(__modti3, .{ .name = "__modti3", .linkage = linkage }); | ||
| 564 | const __multi3 = @import("compiler_rt/multi3.zig").__multi3; | ||
| 565 | @export(__multi3, .{ .name = "__multi3", .linkage = linkage }); | ||
| 566 | const __udivti3 = @import("compiler_rt/udivti3.zig").__udivti3; | ||
| 567 | @export(__udivti3, .{ .name = "__udivti3", .linkage = linkage }); | ||
| 568 | const __udivmodti4 = @import("compiler_rt/udivmodti4.zig").__udivmodti4; | ||
| 569 | @export(__udivmodti4, .{ .name = "__udivmodti4", .linkage = linkage }); | ||
| 570 | const __umodti3 = @import("compiler_rt/umodti3.zig").__umodti3; | ||
| 571 | @export(__umodti3, .{ .name = "__umodti3", .linkage = linkage }); | ||
| 572 | }, | ||
| 573 | .x86_64 => { | ||
| 574 | // The "ti" functions must use Vector(2, u64) parameter types to adhere to the ABI | ||
| 575 | // that LLVM expects compiler-rt to have. | ||
| 576 | const __divti3_windows_x86_64 = @import("compiler_rt/divti3.zig").__divti3_windows_x86_64; | ||
| 577 | @export(__divti3_windows_x86_64, .{ .name = "__divti3", .linkage = linkage }); | ||
| 578 | const __modti3_windows_x86_64 = @import("compiler_rt/modti3.zig").__modti3_windows_x86_64; | ||
| 579 | @export(__modti3_windows_x86_64, .{ .name = "__modti3", .linkage = linkage }); | ||
| 580 | const __multi3_windows_x86_64 = @import("compiler_rt/multi3.zig").__multi3_windows_x86_64; | ||
| 581 | @export(__multi3_windows_x86_64, .{ .name = "__multi3", .linkage = linkage }); | ||
| 582 | const __udivti3_windows_x86_64 = @import("compiler_rt/udivti3.zig").__udivti3_windows_x86_64; | ||
| 583 | @export(__udivti3_windows_x86_64, .{ .name = "__udivti3", .linkage = linkage }); | ||
| 584 | const __udivmodti4_windows_x86_64 = @import("compiler_rt/udivmodti4.zig").__udivmodti4_windows_x86_64; | ||
| 585 | @export(__udivmodti4_windows_x86_64, .{ .name = "__udivmodti4", .linkage = linkage }); | ||
| 586 | const __umodti3_windows_x86_64 = @import("compiler_rt/umodti3.zig").__umodti3_windows_x86_64; | ||
| 587 | @export(__umodti3_windows_x86_64, .{ .name = "__umodti3", .linkage = linkage }); | ||
| 588 | }, | ||
| 589 | else => {}, | ||
| 590 | } | ||
| 591 | if (arch.isAARCH64()) { | ||
| 592 | const __chkstk = @import("compiler_rt/stack_probe.zig").__chkstk; | ||
| 593 | @export(__chkstk, .{ .name = "__chkstk", .linkage = strong_linkage }); | ||
| 594 | const __divti3_windows = @import("compiler_rt/divti3.zig").__divti3; | ||
| 595 | @export(__divti3_windows, .{ .name = "__divti3", .linkage = linkage }); | ||
| 550 | const __modti3 = @import("compiler_rt/modti3.zig").__modti3; | 596 | const __modti3 = @import("compiler_rt/modti3.zig").__modti3; |
| 551 | @export(__modti3, .{ .name = "__modti3", .linkage = linkage }); | 597 | @export(__modti3, .{ .name = "__modti3", .linkage = linkage }); |
| 552 | const __multi3 = @import("compiler_rt/multi3.zig").__multi3; | 598 | const __udivti3_windows = @import("compiler_rt/udivti3.zig").__udivti3; |
| 553 | @export(__multi3, .{ .name = "__multi3", .linkage = linkage }); | 599 | @export(__udivti3_windows, .{ .name = "__udivti3", .linkage = linkage }); |
| 554 | const __udivti3 = @import("compiler_rt/udivti3.zig").__udivti3; | ||
| 555 | @export(__udivti3, .{ .name = "__udivti3", .linkage = linkage }); | ||
| 556 | const __udivmodti4 = @import("compiler_rt/udivmodti4.zig").__udivmodti4; | ||
| 557 | @export(__udivmodti4, .{ .name = "__udivmodti4", .linkage = linkage }); | ||
| 558 | const __umodti3 = @import("compiler_rt/umodti3.zig").__umodti3; | 600 | const __umodti3 = @import("compiler_rt/umodti3.zig").__umodti3; |
| 559 | @export(__umodti3, .{ .name = "__umodti3", .linkage = linkage }); | 601 | @export(__umodti3, .{ .name = "__umodti3", .linkage = linkage }); |
| 560 | }, | 602 | } |
| 561 | .x86_64 => { | 603 | } else { |
| 562 | // The "ti" functions must use Vector(2, u64) parameter types to adhere to the ABI | 604 | const __divti3 = @import("compiler_rt/divti3.zig").__divti3; |
| 563 | // that LLVM expects compiler-rt to have. | 605 | @export(__divti3, .{ .name = "__divti3", .linkage = linkage }); |
| 564 | const __divti3_windows_x86_64 = @import("compiler_rt/divti3.zig").__divti3_windows_x86_64; | ||
| 565 | @export(__divti3_windows_x86_64, .{ .name = "__divti3", .linkage = linkage }); | ||
| 566 | const __modti3_windows_x86_64 = @import("compiler_rt/modti3.zig").__modti3_windows_x86_64; | ||
| 567 | @export(__modti3_windows_x86_64, .{ .name = "__modti3", .linkage = linkage }); | ||
| 568 | const __multi3_windows_x86_64 = @import("compiler_rt/multi3.zig").__multi3_windows_x86_64; | ||
| 569 | @export(__multi3_windows_x86_64, .{ .name = "__multi3", .linkage = linkage }); | ||
| 570 | const __udivti3_windows_x86_64 = @import("compiler_rt/udivti3.zig").__udivti3_windows_x86_64; | ||
| 571 | @export(__udivti3_windows_x86_64, .{ .name = "__udivti3", .linkage = linkage }); | ||
| 572 | const __udivmodti4_windows_x86_64 = @import("compiler_rt/udivmodti4.zig").__udivmodti4_windows_x86_64; | ||
| 573 | @export(__udivmodti4_windows_x86_64, .{ .name = "__udivmodti4", .linkage = linkage }); | ||
| 574 | const __umodti3_windows_x86_64 = @import("compiler_rt/umodti3.zig").__umodti3_windows_x86_64; | ||
| 575 | @export(__umodti3_windows_x86_64, .{ .name = "__umodti3", .linkage = linkage }); | ||
| 576 | }, | ||
| 577 | else => {}, | ||
| 578 | } | ||
| 579 | if (arch.isAARCH64()) { | ||
| 580 | const __chkstk = @import("compiler_rt/stack_probe.zig").__chkstk; | ||
| 581 | @export(__chkstk, .{ .name = "__chkstk", .linkage = strong_linkage }); | ||
| 582 | const __divti3_windows = @import("compiler_rt/divti3.zig").__divti3; | ||
| 583 | @export(__divti3_windows, .{ .name = "__divti3", .linkage = linkage }); | ||
| 584 | const __modti3 = @import("compiler_rt/modti3.zig").__modti3; | 606 | const __modti3 = @import("compiler_rt/modti3.zig").__modti3; |
| 585 | @export(__modti3, .{ .name = "__modti3", .linkage = linkage }); | 607 | @export(__modti3, .{ .name = "__modti3", .linkage = linkage }); |
| 586 | const __udivti3_windows = @import("compiler_rt/udivti3.zig").__udivti3; | 608 | const __multi3 = @import("compiler_rt/multi3.zig").__multi3; |
| 587 | @export(__udivti3_windows, .{ .name = "__udivti3", .linkage = linkage }); | 609 | @export(__multi3, .{ .name = "__multi3", .linkage = linkage }); |
| 610 | const __udivti3 = @import("compiler_rt/udivti3.zig").__udivti3; | ||
| 611 | @export(__udivti3, .{ .name = "__udivti3", .linkage = linkage }); | ||
| 612 | const __udivmodti4 = @import("compiler_rt/udivmodti4.zig").__udivmodti4; | ||
| 613 | @export(__udivmodti4, .{ .name = "__udivmodti4", .linkage = linkage }); | ||
| 588 | const __umodti3 = @import("compiler_rt/umodti3.zig").__umodti3; | 614 | const __umodti3 = @import("compiler_rt/umodti3.zig").__umodti3; |
| 589 | @export(__umodti3, .{ .name = "__umodti3", .linkage = linkage }); | 615 | @export(__umodti3, .{ .name = "__umodti3", .linkage = linkage }); |
| 590 | } | 616 | } |
| 591 | } else { | 617 | const __muloti4 = @import("compiler_rt/muloti4.zig").__muloti4; |
| 592 | const __divti3 = @import("compiler_rt/divti3.zig").__divti3; | 618 | @export(__muloti4, .{ .name = "__muloti4", .linkage = linkage }); |
| 593 | @export(__divti3, .{ .name = "__divti3", .linkage = linkage }); | 619 | const __mulodi4 = @import("compiler_rt/mulodi4.zig").__mulodi4; |
| 594 | const __modti3 = @import("compiler_rt/modti3.zig").__modti3; | 620 | @export(__mulodi4, .{ .name = "__mulodi4", .linkage = linkage }); |
| 595 | @export(__modti3, .{ .name = "__modti3", .linkage = linkage }); | ||
| 596 | const __multi3 = @import("compiler_rt/multi3.zig").__multi3; | ||
| 597 | @export(__multi3, .{ .name = "__multi3", .linkage = linkage }); | ||
| 598 | const __udivti3 = @import("compiler_rt/udivti3.zig").__udivti3; | ||
| 599 | @export(__udivti3, .{ .name = "__udivti3", .linkage = linkage }); | ||
| 600 | const __udivmodti4 = @import("compiler_rt/udivmodti4.zig").__udivmodti4; | ||
| 601 | @export(__udivmodti4, .{ .name = "__udivmodti4", .linkage = linkage }); | ||
| 602 | const __umodti3 = @import("compiler_rt/umodti3.zig").__umodti3; | ||
| 603 | @export(__umodti3, .{ .name = "__umodti3", .linkage = linkage }); | ||
| 604 | } | ||
| 605 | const __muloti4 = @import("compiler_rt/muloti4.zig").__muloti4; | ||
| 606 | @export(__muloti4, .{ .name = "__muloti4", .linkage = linkage }); | ||
| 607 | const __mulodi4 = @import("compiler_rt/mulodi4.zig").__mulodi4; | ||
| 608 | @export(__mulodi4, .{ .name = "__mulodi4", .linkage = linkage }); | ||
| 609 | 621 | ||
| 610 | _ = @import("compiler_rt/atomics.zig"); | 622 | _ = @import("compiler_rt/atomics.zig"); |
| 623 | } | ||
| 611 | } | 624 | } |
| 612 | 625 | ||
| 613 | // Avoid dragging in the runtime safety mechanisms into this .o file, | 626 | // Avoid dragging in the runtime safety mechanisms into this .o file, |
| 614 | // unless we're trying to test this file. | 627 | // unless we're trying to test this file. |
| 615 | pub fn panic(msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn { | 628 | pub fn panic(msg: []const u8, error_return_trace: ?*std.builtin.StackTrace) noreturn { |
| 616 | _ = error_return_trace; | 629 | _ = error_return_trace; |
| 617 | @setCold(true); | 630 | @setCold(true); |
| 631 | if (builtin.zig_is_stage2) { | ||
| 632 | while (true) { | ||
| 633 | @breakpoint(); | ||
| 634 | } | ||
| 635 | } | ||
| 618 | if (is_test) { | 636 | if (is_test) { |
| 619 | std.debug.panic("{s}", .{msg}); | 637 | std.debug.panic("{s}", .{msg}); |
| 620 | } else { | 638 | } else { |
lib/std/special/compiler_rt/extendXfYf2.zig+6-6| ... | @@ -3,23 +3,23 @@ const builtin = @import("builtin"); | ... | @@ -3,23 +3,23 @@ const builtin = @import("builtin"); |
| 3 | const is_test = builtin.is_test; | 3 | const is_test = builtin.is_test; |
| 4 | 4 | ||
| 5 | pub fn __extendsfdf2(a: f32) callconv(.C) f64 { | 5 | pub fn __extendsfdf2(a: f32) callconv(.C) f64 { |
| 6 | return @call(.{ .modifier = .always_inline }, extendXfYf2, .{ f64, f32, @bitCast(u32, a) }); | 6 | return extendXfYf2(f64, f32, @bitCast(u32, a)); |
| 7 | } | 7 | } |
| 8 | 8 | ||
| 9 | pub fn __extenddftf2(a: f64) callconv(.C) f128 { | 9 | pub fn __extenddftf2(a: f64) callconv(.C) f128 { |
| 10 | return @call(.{ .modifier = .always_inline }, extendXfYf2, .{ f128, f64, @bitCast(u64, a) }); | 10 | return extendXfYf2(f128, f64, @bitCast(u64, a)); |
| 11 | } | 11 | } |
| 12 | 12 | ||
| 13 | pub fn __extendsftf2(a: f32) callconv(.C) f128 { | 13 | pub fn __extendsftf2(a: f32) callconv(.C) f128 { |
| 14 | return @call(.{ .modifier = .always_inline }, extendXfYf2, .{ f128, f32, @bitCast(u32, a) }); | 14 | return extendXfYf2(f128, f32, @bitCast(u32, a)); |
| 15 | } | 15 | } |
| 16 | 16 | ||
| 17 | pub fn __extendhfsf2(a: u16) callconv(.C) f32 { | 17 | pub fn __extendhfsf2(a: u16) callconv(.C) f32 { |
| 18 | return @call(.{ .modifier = .always_inline }, extendXfYf2, .{ f32, f16, a }); | 18 | return extendXfYf2(f32, f16, a); |
| 19 | } | 19 | } |
| 20 | 20 | ||
| 21 | pub fn __extendhftf2(a: u16) callconv(.C) f128 { | 21 | pub fn __extendhftf2(a: u16) callconv(.C) f128 { |
| 22 | return @call(.{ .modifier = .always_inline }, extendXfYf2, .{ f128, f16, a }); | 22 | return extendXfYf2(f128, f16, a); |
| 23 | } | 23 | } |
| 24 | 24 | ||
| 25 | pub fn __aeabi_h2f(arg: u16) callconv(.AAPCS) f32 { | 25 | pub fn __aeabi_h2f(arg: u16) callconv(.AAPCS) f32 { |
| ... | @@ -34,7 +34,7 @@ pub fn __aeabi_f2d(arg: f32) callconv(.AAPCS) f64 { | ... | @@ -34,7 +34,7 @@ pub fn __aeabi_f2d(arg: f32) callconv(.AAPCS) f64 { |
| 34 | 34 | ||
| 35 | const CHAR_BIT = 8; | 35 | const CHAR_BIT = 8; |
| 36 | 36 | ||
| 37 | fn extendXfYf2(comptime dst_t: type, comptime src_t: type, a: std.meta.Int(.unsigned, @typeInfo(src_t).Float.bits)) dst_t { | 37 | inline fn extendXfYf2(comptime dst_t: type, comptime src_t: type, a: std.meta.Int(.unsigned, @typeInfo(src_t).Float.bits)) dst_t { |
| 38 | @setRuntimeSafety(builtin.is_test); | 38 | @setRuntimeSafety(builtin.is_test); |
| 39 | 39 | ||
| 40 | const src_rep_t = std.meta.Int(.unsigned, @typeInfo(src_t).Float.bits); | 40 | const src_rep_t = std.meta.Int(.unsigned, @typeInfo(src_t).Float.bits); |
src/Air.zig+7-3| ... | @@ -227,9 +227,12 @@ pub const Inst = struct { | ... | @@ -227,9 +227,12 @@ pub const Inst = struct { |
| 227 | /// Indicates the program counter will never get to this instruction. | 227 | /// Indicates the program counter will never get to this instruction. |
| 228 | /// Result type is always noreturn; no instructions in a block follow this one. | 228 | /// Result type is always noreturn; no instructions in a block follow this one. |
| 229 | unreach, | 229 | unreach, |
| 230 | /// Convert from one float type to another. | 230 | /// Convert from a float type to a smaller one. |
| 231 | /// Uses the `ty_op` field. | 231 | /// Uses the `ty_op` field. |
| 232 | floatcast, | 232 | fptrunc, |
| 233 | /// Convert from a float type to a wider one. | ||
| 234 | /// Uses the `ty_op` field. | ||
| 235 | fpext, | ||
| 233 | /// Returns an integer with a different type than the operand. The new type may have | 236 | /// Returns an integer with a different type than the operand. The new type may have |
| 234 | /// fewer, the same, or more bits than the operand type. However, the instruction | 237 | /// fewer, the same, or more bits than the operand type. However, the instruction |
| 235 | /// guarantees that the same integer value fits in both types. | 238 | /// guarantees that the same integer value fits in both types. |
| ... | @@ -586,7 +589,8 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type { | ... | @@ -586,7 +589,8 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type { |
| 586 | .not, | 589 | .not, |
| 587 | .bitcast, | 590 | .bitcast, |
| 588 | .load, | 591 | .load, |
| 589 | .floatcast, | 592 | .fpext, |
| 593 | .fptrunc, | ||
| 590 | .intcast, | 594 | .intcast, |
| 591 | .trunc, | 595 | .trunc, |
| 592 | .optional_payload, | 596 | .optional_payload, |
src/AstGen.zig+49-25| ... | @@ -2166,6 +2166,7 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner | ... | @@ -2166,6 +2166,7 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner |
| 2166 | .ensure_result_used, | 2166 | .ensure_result_used, |
| 2167 | .ensure_result_non_error, | 2167 | .ensure_result_non_error, |
| 2168 | .@"export", | 2168 | .@"export", |
| 2169 | .export_value, | ||
| 2169 | .set_eval_branch_quota, | 2170 | .set_eval_branch_quota, |
| 2170 | .ensure_err_payload_void, | 2171 | .ensure_err_payload_void, |
| 2171 | .atomic_store, | 2172 | .atomic_store, |
| ... | @@ -7095,32 +7096,55 @@ fn builtinCall( | ... | @@ -7095,32 +7096,55 @@ fn builtinCall( |
| 7095 | .identifier => { | 7096 | .identifier => { |
| 7096 | const ident_token = main_tokens[params[0]]; | 7097 | const ident_token = main_tokens[params[0]]; |
| 7097 | decl_name = try astgen.identAsString(ident_token); | 7098 | decl_name = try astgen.identAsString(ident_token); |
| 7098 | { | 7099 | |
| 7099 | var s = scope; | 7100 | var s = scope; |
| 7100 | while (true) switch (s.tag) { | 7101 | var found_already: ?Ast.Node.Index = null; // we have found a decl with the same name already |
| 7101 | .local_val => { | 7102 | while (true) switch (s.tag) { |
| 7102 | const local_val = s.cast(Scope.LocalVal).?; | 7103 | .local_val => { |
| 7103 | if (local_val.name == decl_name) { | 7104 | const local_val = s.cast(Scope.LocalVal).?; |
| 7104 | local_val.used = true; | 7105 | if (local_val.name == decl_name) { |
| 7105 | break; | 7106 | local_val.used = true; |
| 7106 | } | 7107 | _ = try gz.addPlNode(.export_value, node, Zir.Inst.ExportValue{ |
| 7107 | s = local_val.parent; | 7108 | .operand = local_val.inst, |
| 7108 | }, | 7109 | .options = try comptimeExpr(gz, scope, .{ .coerced_ty = .export_options_type }, params[1]), |
| 7109 | .local_ptr => { | 7110 | }); |
| 7110 | const local_ptr = s.cast(Scope.LocalPtr).?; | 7111 | return rvalue(gz, rl, .void_value, node); |
| 7111 | if (local_ptr.name == decl_name) { | 7112 | } |
| 7112 | if (!local_ptr.maybe_comptime) | 7113 | s = local_val.parent; |
| 7113 | return astgen.failNode(params[0], "unable to export runtime-known value", .{}); | 7114 | }, |
| 7114 | local_ptr.used = true; | 7115 | .local_ptr => { |
| 7115 | break; | 7116 | const local_ptr = s.cast(Scope.LocalPtr).?; |
| 7117 | if (local_ptr.name == decl_name) { | ||
| 7118 | if (!local_ptr.maybe_comptime) | ||
| 7119 | return astgen.failNode(params[0], "unable to export runtime-known value", .{}); | ||
| 7120 | local_ptr.used = true; | ||
| 7121 | const loaded = try gz.addUnNode(.load, local_ptr.ptr, node); | ||
| 7122 | _ = try gz.addPlNode(.export_value, node, Zir.Inst.ExportValue{ | ||
| 7123 | .operand = loaded, | ||
| 7124 | .options = try comptimeExpr(gz, scope, .{ .coerced_ty = .export_options_type }, params[1]), | ||
| 7125 | }); | ||
| 7126 | return rvalue(gz, rl, .void_value, node); | ||
| 7127 | } | ||
| 7128 | s = local_ptr.parent; | ||
| 7129 | }, | ||
| 7130 | .gen_zir => s = s.cast(GenZir).?.parent, | ||
| 7131 | .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent, | ||
| 7132 | .namespace => { | ||
| 7133 | const ns = s.cast(Scope.Namespace).?; | ||
| 7134 | if (ns.decls.get(decl_name)) |i| { | ||
| 7135 | if (found_already) |f| { | ||
| 7136 | return astgen.failNodeNotes(node, "ambiguous reference", .{}, &.{ | ||
| 7137 | try astgen.errNoteNode(f, "declared here", .{}), | ||
| 7138 | try astgen.errNoteNode(i, "also declared here", .{}), | ||
| 7139 | }); | ||
| 7116 | } | 7140 | } |
| 7117 | s = local_ptr.parent; | 7141 | // We found a match but must continue looking for ambiguous references to decls. |
| 7118 | }, | 7142 | found_already = i; |
| 7119 | .gen_zir => s = s.cast(GenZir).?.parent, | 7143 | } |
| 7120 | .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent, | 7144 | s = ns.parent; |
| 7121 | .namespace, .top => break, | 7145 | }, |
| 7122 | }; | 7146 | .top => break, |
| 7123 | } | 7147 | }; |
| 7124 | }, | 7148 | }, |
| 7125 | .field_access => { | 7149 | .field_access => { |
| 7126 | const namespace_node = node_datas[params[0]].lhs; | 7150 | const namespace_node = node_datas[params[0]].lhs; |
src/Liveness.zig+2-1| ... | @@ -274,7 +274,8 @@ fn analyzeInst( | ... | @@ -274,7 +274,8 @@ fn analyzeInst( |
| 274 | .not, | 274 | .not, |
| 275 | .bitcast, | 275 | .bitcast, |
| 276 | .load, | 276 | .load, |
| 277 | .floatcast, | 277 | .fpext, |
| 278 | .fptrunc, | ||
| 278 | .intcast, | 279 | .intcast, |
| 279 | .trunc, | 280 | .trunc, |
| 280 | .optional_payload, | 281 | .optional_payload, |
src/Module.zig+27-15| ... | @@ -2389,6 +2389,7 @@ pub fn deinit(mod: *Module) void { | ... | @@ -2389,6 +2389,7 @@ pub fn deinit(mod: *Module) void { |
| 2389 | fn freeExportList(gpa: *Allocator, export_list: []*Export) void { | 2389 | fn freeExportList(gpa: *Allocator, export_list: []*Export) void { |
| 2390 | for (export_list) |exp| { | 2390 | for (export_list) |exp| { |
| 2391 | gpa.free(exp.options.name); | 2391 | gpa.free(exp.options.name); |
| 2392 | if (exp.options.section) |s| gpa.free(s); | ||
| 2392 | gpa.destroy(exp); | 2393 | gpa.destroy(exp); |
| 2393 | } | 2394 | } |
| 2394 | gpa.free(export_list); | 2395 | gpa.free(export_list); |
| ... | @@ -3317,7 +3318,8 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool { | ... | @@ -3317,7 +3318,8 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool { |
| 3317 | return mod.fail(&block_scope.base, export_src, "export of inline function", .{}); | 3318 | return mod.fail(&block_scope.base, export_src, "export of inline function", .{}); |
| 3318 | } | 3319 | } |
| 3319 | // The scope needs to have the decl in it. | 3320 | // The scope needs to have the decl in it. |
| 3320 | try mod.analyzeExport(&block_scope.base, export_src, mem.spanZ(decl.name), decl); | 3321 | const options: std.builtin.ExportOptions = .{ .name = mem.spanZ(decl.name) }; |
| 3322 | try mod.analyzeExport(&block_scope.base, export_src, options, decl); | ||
| 3321 | } | 3323 | } |
| 3322 | return type_changed or is_inline != prev_is_inline; | 3324 | return type_changed or is_inline != prev_is_inline; |
| 3323 | } | 3325 | } |
| ... | @@ -3376,7 +3378,8 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool { | ... | @@ -3376,7 +3378,8 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool { |
| 3376 | if (decl.is_exported) { | 3378 | if (decl.is_exported) { |
| 3377 | const export_src = src; // TODO point to the export token | 3379 | const export_src = src; // TODO point to the export token |
| 3378 | // The scope needs to have the decl in it. | 3380 | // The scope needs to have the decl in it. |
| 3379 | try mod.analyzeExport(&block_scope.base, export_src, mem.spanZ(decl.name), decl); | 3381 | const options: std.builtin.ExportOptions = .{ .name = mem.spanZ(decl.name) }; |
| 3382 | try mod.analyzeExport(&block_scope.base, export_src, options, decl); | ||
| 3380 | } | 3383 | } |
| 3381 | 3384 | ||
| 3382 | return type_changed; | 3385 | return type_changed; |
| ... | @@ -4119,7 +4122,7 @@ pub fn analyzeExport( | ... | @@ -4119,7 +4122,7 @@ pub fn analyzeExport( |
| 4119 | mod: *Module, | 4122 | mod: *Module, |
| 4120 | scope: *Scope, | 4123 | scope: *Scope, |
| 4121 | src: LazySrcLoc, | 4124 | src: LazySrcLoc, |
| 4122 | borrowed_symbol_name: []const u8, | 4125 | borrowed_options: std.builtin.ExportOptions, |
| 4123 | exported_decl: *Decl, | 4126 | exported_decl: *Decl, |
| 4124 | ) !void { | 4127 | ) !void { |
| 4125 | try mod.ensureDeclAnalyzed(exported_decl); | 4128 | try mod.ensureDeclAnalyzed(exported_decl); |
| ... | @@ -4128,23 +4131,32 @@ pub fn analyzeExport( | ... | @@ -4128,23 +4131,32 @@ pub fn analyzeExport( |
| 4128 | else => return mod.fail(scope, src, "unable to export type '{}'", .{exported_decl.ty}), | 4131 | else => return mod.fail(scope, src, "unable to export type '{}'", .{exported_decl.ty}), |
| 4129 | } | 4132 | } |
| 4130 | 4133 | ||
| 4131 | try mod.decl_exports.ensureUnusedCapacity(mod.gpa, 1); | 4134 | const gpa = mod.gpa; |
| 4132 | try mod.export_owners.ensureUnusedCapacity(mod.gpa, 1); | 4135 | |
| 4136 | try mod.decl_exports.ensureUnusedCapacity(gpa, 1); | ||
| 4137 | try mod.export_owners.ensureUnusedCapacity(gpa, 1); | ||
| 4133 | 4138 | ||
| 4134 | const new_export = try mod.gpa.create(Export); | 4139 | const new_export = try gpa.create(Export); |
| 4135 | errdefer mod.gpa.destroy(new_export); | 4140 | errdefer gpa.destroy(new_export); |
| 4136 | 4141 | ||
| 4137 | const symbol_name = try mod.gpa.dupe(u8, borrowed_symbol_name); | 4142 | const symbol_name = try gpa.dupe(u8, borrowed_options.name); |
| 4138 | errdefer mod.gpa.free(symbol_name); | 4143 | errdefer gpa.free(symbol_name); |
| 4144 | |||
| 4145 | const section: ?[]const u8 = if (borrowed_options.section) |s| try gpa.dupe(u8, s) else null; | ||
| 4146 | errdefer if (section) |s| gpa.free(s); | ||
| 4139 | 4147 | ||
| 4140 | const owner_decl = scope.ownerDecl().?; | 4148 | const owner_decl = scope.ownerDecl().?; |
| 4141 | 4149 | ||
| 4142 | log.debug("exporting Decl '{s}' as symbol '{s}' from Decl '{s}'", .{ | 4150 | log.debug("exporting Decl '{s}' as symbol '{s}' from Decl '{s}'", .{ |
| 4143 | exported_decl.name, borrowed_symbol_name, owner_decl.name, | 4151 | exported_decl.name, symbol_name, owner_decl.name, |
| 4144 | }); | 4152 | }); |
| 4145 | 4153 | ||
| 4146 | new_export.* = .{ | 4154 | new_export.* = .{ |
| 4147 | .options = .{ .name = symbol_name }, | 4155 | .options = .{ |
| 4156 | .name = symbol_name, | ||
| 4157 | .linkage = borrowed_options.linkage, | ||
| 4158 | .section = section, | ||
| 4159 | }, | ||
| 4148 | .src = src, | 4160 | .src = src, |
| 4149 | .link = switch (mod.comp.bin_file.tag) { | 4161 | .link = switch (mod.comp.bin_file.tag) { |
| 4150 | .coff => .{ .coff = {} }, | 4162 | .coff => .{ .coff = {} }, |
| ... | @@ -4165,18 +4177,18 @@ pub fn analyzeExport( | ... | @@ -4165,18 +4177,18 @@ pub fn analyzeExport( |
| 4165 | if (!eo_gop.found_existing) { | 4177 | if (!eo_gop.found_existing) { |
| 4166 | eo_gop.value_ptr.* = &[0]*Export{}; | 4178 | eo_gop.value_ptr.* = &[0]*Export{}; |
| 4167 | } | 4179 | } |
| 4168 | eo_gop.value_ptr.* = try mod.gpa.realloc(eo_gop.value_ptr.*, eo_gop.value_ptr.len + 1); | 4180 | eo_gop.value_ptr.* = try gpa.realloc(eo_gop.value_ptr.*, eo_gop.value_ptr.len + 1); |
| 4169 | eo_gop.value_ptr.*[eo_gop.value_ptr.len - 1] = new_export; | 4181 | eo_gop.value_ptr.*[eo_gop.value_ptr.len - 1] = new_export; |
| 4170 | errdefer eo_gop.value_ptr.* = mod.gpa.shrink(eo_gop.value_ptr.*, eo_gop.value_ptr.len - 1); | 4182 | errdefer eo_gop.value_ptr.* = gpa.shrink(eo_gop.value_ptr.*, eo_gop.value_ptr.len - 1); |
| 4171 | 4183 | ||
| 4172 | // Add to exported_decl table. | 4184 | // Add to exported_decl table. |
| 4173 | const de_gop = mod.decl_exports.getOrPutAssumeCapacity(exported_decl); | 4185 | const de_gop = mod.decl_exports.getOrPutAssumeCapacity(exported_decl); |
| 4174 | if (!de_gop.found_existing) { | 4186 | if (!de_gop.found_existing) { |
| 4175 | de_gop.value_ptr.* = &[0]*Export{}; | 4187 | de_gop.value_ptr.* = &[0]*Export{}; |
| 4176 | } | 4188 | } |
| 4177 | de_gop.value_ptr.* = try mod.gpa.realloc(de_gop.value_ptr.*, de_gop.value_ptr.len + 1); | 4189 | de_gop.value_ptr.* = try gpa.realloc(de_gop.value_ptr.*, de_gop.value_ptr.len + 1); |
| 4178 | de_gop.value_ptr.*[de_gop.value_ptr.len - 1] = new_export; | 4190 | de_gop.value_ptr.*[de_gop.value_ptr.len - 1] = new_export; |
| 4179 | errdefer de_gop.value_ptr.* = mod.gpa.shrink(de_gop.value_ptr.*, de_gop.value_ptr.len - 1); | 4191 | errdefer de_gop.value_ptr.* = gpa.shrink(de_gop.value_ptr.*, de_gop.value_ptr.len - 1); |
| 4180 | } | 4192 | } |
| 4181 | 4193 | ||
| 4182 | /// Takes ownership of `name` even if it returns an error. | 4194 | /// Takes ownership of `name` even if it returns an error. |
src/Sema.zig+97-39| ... | @@ -458,6 +458,11 @@ pub fn analyzeBody( | ... | @@ -458,6 +458,11 @@ pub fn analyzeBody( |
| 458 | i += 1; | 458 | i += 1; |
| 459 | continue; | 459 | continue; |
| 460 | }, | 460 | }, |
| 461 | .export_value => { | ||
| 462 | try sema.zirExportValue(block, inst); | ||
| 463 | i += 1; | ||
| 464 | continue; | ||
| 465 | }, | ||
| 461 | .set_align_stack => { | 466 | .set_align_stack => { |
| 462 | try sema.zirSetAlignStack(block, inst); | 467 | try sema.zirSetAlignStack(block, inst); |
| 463 | i += 1; | 468 | i += 1; |
| ... | @@ -2392,30 +2397,33 @@ fn zirExport(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErro | ... | @@ -2392,30 +2397,33 @@ fn zirExport(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErro |
| 2392 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 2397 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 2393 | const extra = sema.code.extraData(Zir.Inst.Export, inst_data.payload_index).data; | 2398 | const extra = sema.code.extraData(Zir.Inst.Export, inst_data.payload_index).data; |
| 2394 | const src = inst_data.src(); | 2399 | const src = inst_data.src(); |
| 2395 | const lhs_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; | 2400 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| 2396 | const rhs_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; | 2401 | const options_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; |
| 2397 | const decl_name = sema.code.nullTerminatedString(extra.decl_name); | 2402 | const decl_name = sema.code.nullTerminatedString(extra.decl_name); |
| 2398 | if (extra.namespace != .none) { | 2403 | if (extra.namespace != .none) { |
| 2399 | return sema.mod.fail(&block.base, src, "TODO: implement exporting with field access", .{}); | 2404 | return sema.mod.fail(&block.base, src, "TODO: implement exporting with field access", .{}); |
| 2400 | } | 2405 | } |
| 2401 | const decl = try sema.lookupIdentifier(block, lhs_src, decl_name); | 2406 | const decl = try sema.lookupIdentifier(block, operand_src, decl_name); |
| 2402 | const options = try sema.resolveInstConst(block, rhs_src, extra.options); | 2407 | const options = try sema.resolveExportOptions(block, options_src, extra.options); |
| 2403 | const struct_obj = options.ty.castTag(.@"struct").?.data; | 2408 | try sema.mod.analyzeExport(&block.base, src, options, decl); |
| 2404 | const fields = options.val.castTag(.@"struct").?.data[0..struct_obj.fields.count()]; | 2409 | } |
| 2405 | const name_index = struct_obj.fields.getIndex("name").?; | ||
| 2406 | const linkage_index = struct_obj.fields.getIndex("linkage").?; | ||
| 2407 | const section_index = struct_obj.fields.getIndex("section").?; | ||
| 2408 | const export_name = try fields[name_index].toAllocatedBytes(sema.arena); | ||
| 2409 | const linkage = fields[linkage_index].toEnum(std.builtin.GlobalLinkage); | ||
| 2410 | 2410 | ||
| 2411 | if (linkage != .Strong) { | 2411 | fn zirExportValue(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!void { |
| 2412 | return sema.mod.fail(&block.base, src, "TODO: implement exporting with non-strong linkage", .{}); | 2412 | const tracy = trace(@src()); |
| 2413 | } | 2413 | defer tracy.end(); |
| 2414 | if (!fields[section_index].isNull()) { | ||
| 2415 | return sema.mod.fail(&block.base, src, "TODO: implement exporting with linksection", .{}); | ||
| 2416 | } | ||
| 2417 | 2414 | ||
| 2418 | try sema.mod.analyzeExport(&block.base, src, export_name, decl); | 2415 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 2416 | const extra = sema.code.extraData(Zir.Inst.ExportValue, inst_data.payload_index).data; | ||
| 2417 | const src = inst_data.src(); | ||
| 2418 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; | ||
| 2419 | const options_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; | ||
| 2420 | const operand = try sema.resolveInstConst(block, operand_src, extra.operand); | ||
| 2421 | const options = try sema.resolveExportOptions(block, options_src, extra.options); | ||
| 2422 | const decl = switch (operand.val.tag()) { | ||
| 2423 | .function => operand.val.castTag(.function).?.data.owner_decl, | ||
| 2424 | else => return sema.mod.fail(&block.base, operand_src, "TODO implement exporting arbitrary Value objects", .{}), // TODO put this Value into an anonymous Decl and then export it. | ||
| 2425 | }; | ||
| 2426 | try sema.mod.analyzeExport(&block.base, src, options, decl); | ||
| 2419 | } | 2427 | } |
| 2420 | 2428 | ||
| 2421 | fn zirSetAlignStack(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!void { | 2429 | fn zirSetAlignStack(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!void { |
| ... | @@ -4516,11 +4524,18 @@ fn zirFloatCast(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileE | ... | @@ -4516,11 +4524,18 @@ fn zirFloatCast(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileE |
| 4516 | 4524 | ||
| 4517 | if (try sema.isComptimeKnown(block, operand_src, operand)) { | 4525 | if (try sema.isComptimeKnown(block, operand_src, operand)) { |
| 4518 | return sema.coerce(block, dest_type, operand, operand_src); | 4526 | return sema.coerce(block, dest_type, operand, operand_src); |
| 4519 | } else if (dest_is_comptime_float) { | 4527 | } |
| 4528 | if (dest_is_comptime_float) { | ||
| 4520 | return sema.mod.fail(&block.base, src, "unable to cast runtime value to 'comptime_float'", .{}); | 4529 | return sema.mod.fail(&block.base, src, "unable to cast runtime value to 'comptime_float'", .{}); |
| 4521 | } | 4530 | } |
| 4522 | 4531 | const target = sema.mod.getTarget(); | |
| 4523 | return sema.mod.fail(&block.base, src, "TODO implement analyze widen or shorten float", .{}); | 4532 | const src_bits = operand_ty.floatBits(target); |
| 4533 | const dst_bits = dest_type.floatBits(target); | ||
| 4534 | if (dst_bits >= src_bits) { | ||
| 4535 | return sema.coerce(block, dest_type, operand, operand_src); | ||
| 4536 | } | ||
| 4537 | try sema.requireRuntimeBlock(block, operand_src); | ||
| 4538 | return block.addTyOp(.fptrunc, dest_type, operand); | ||
| 4524 | } | 4539 | } |
| 4525 | 4540 | ||
| 4526 | fn zirElemVal(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 4541 | fn zirElemVal(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | @@ -7936,6 +7951,31 @@ fn checkAtomicOperandType( | ... | @@ -7936,6 +7951,31 @@ fn checkAtomicOperandType( |
| 7936 | } | 7951 | } |
| 7937 | } | 7952 | } |
| 7938 | 7953 | ||
| 7954 | fn resolveExportOptions( | ||
| 7955 | sema: *Sema, | ||
| 7956 | block: *Scope.Block, | ||
| 7957 | src: LazySrcLoc, | ||
| 7958 | zir_ref: Zir.Inst.Ref, | ||
| 7959 | ) CompileError!std.builtin.ExportOptions { | ||
| 7960 | const export_options_ty = try sema.getBuiltinType(block, src, "ExportOptions"); | ||
| 7961 | const air_ref = sema.resolveInst(zir_ref); | ||
| 7962 | const coerced = try sema.coerce(block, export_options_ty, air_ref, src); | ||
| 7963 | const val = try sema.resolveConstValue(block, src, coerced); | ||
| 7964 | const fields = val.castTag(.@"struct").?.data; | ||
| 7965 | const struct_obj = export_options_ty.castTag(.@"struct").?.data; | ||
| 7966 | const name_index = struct_obj.fields.getIndex("name").?; | ||
| 7967 | const linkage_index = struct_obj.fields.getIndex("linkage").?; | ||
| 7968 | const section_index = struct_obj.fields.getIndex("section").?; | ||
| 7969 | if (!fields[section_index].isNull()) { | ||
| 7970 | return sema.mod.fail(&block.base, src, "TODO: implement exporting with linksection", .{}); | ||
| 7971 | } | ||
| 7972 | return std.builtin.ExportOptions{ | ||
| 7973 | .name = try fields[name_index].toAllocatedBytes(sema.arena), | ||
| 7974 | .linkage = fields[linkage_index].toEnum(std.builtin.GlobalLinkage), | ||
| 7975 | .section = null, // TODO | ||
| 7976 | }; | ||
| 7977 | } | ||
| 7978 | |||
| 7939 | fn resolveAtomicOrder( | 7979 | fn resolveAtomicOrder( |
| 7940 | sema: *Sema, | 7980 | sema: *Sema, |
| 7941 | block: *Scope.Block, | 7981 | block: *Scope.Block, |
| ... | @@ -9581,7 +9621,7 @@ fn coerce( | ... | @@ -9581,7 +9621,7 @@ fn coerce( |
| 9581 | const dst_bits = dest_type.floatBits(target); | 9621 | const dst_bits = dest_type.floatBits(target); |
| 9582 | if (dst_bits >= src_bits) { | 9622 | if (dst_bits >= src_bits) { |
| 9583 | try sema.requireRuntimeBlock(block, inst_src); | 9623 | try sema.requireRuntimeBlock(block, inst_src); |
| 9584 | return block.addTyOp(.floatcast, dest_type, inst); | 9624 | return block.addTyOp(.fpext, dest_type, inst); |
| 9585 | } | 9625 | } |
| 9586 | } | 9626 | } |
| 9587 | }, | 9627 | }, |
| ... | @@ -9729,35 +9769,53 @@ fn coerceNum( | ... | @@ -9729,35 +9769,53 @@ fn coerceNum( |
| 9729 | const target = sema.mod.getTarget(); | 9769 | const target = sema.mod.getTarget(); |
| 9730 | 9770 | ||
| 9731 | switch (dst_zig_tag) { | 9771 | switch (dst_zig_tag) { |
| 9732 | .ComptimeInt, .Int => { | 9772 | .ComptimeInt, .Int => switch (src_zig_tag) { |
| 9733 | if (src_zig_tag == .Float or src_zig_tag == .ComptimeFloat) { | 9773 | .Float, .ComptimeFloat => { |
| 9734 | if (val.floatHasFraction()) { | 9774 | if (val.floatHasFraction()) { |
| 9735 | return sema.mod.fail(&block.base, inst_src, "fractional component prevents float value {} from being casted to type '{}'", .{ val, inst_ty }); | 9775 | return sema.mod.fail(&block.base, inst_src, "fractional component prevents float value {} from coercion to type '{}'", .{ val, dest_type }); |
| 9736 | } | 9776 | } |
| 9737 | return sema.mod.fail(&block.base, inst_src, "TODO float to int", .{}); | 9777 | return sema.mod.fail(&block.base, inst_src, "TODO float to int", .{}); |
| 9738 | } else if (src_zig_tag == .Int or src_zig_tag == .ComptimeInt) { | 9778 | }, |
| 9779 | .Int, .ComptimeInt => { | ||
| 9739 | if (!val.intFitsInType(dest_type, target)) { | 9780 | if (!val.intFitsInType(dest_type, target)) { |
| 9740 | return sema.mod.fail(&block.base, inst_src, "type {} cannot represent integer value {}", .{ dest_type, val }); | 9781 | return sema.mod.fail(&block.base, inst_src, "type {} cannot represent integer value {}", .{ dest_type, val }); |
| 9741 | } | 9782 | } |
| 9742 | return try sema.addConstant(dest_type, val); | 9783 | return try sema.addConstant(dest_type, val); |
| 9743 | } | 9784 | }, |
| 9785 | else => {}, | ||
| 9744 | }, | 9786 | }, |
| 9745 | .ComptimeFloat, .Float => { | 9787 | .ComptimeFloat, .Float => switch (src_zig_tag) { |
| 9746 | if (src_zig_tag == .Float or src_zig_tag == .ComptimeFloat) { | 9788 | .ComptimeFloat => { |
| 9747 | const res = val.floatCast(sema.arena, dest_type) catch |err| switch (err) { | 9789 | const result_val = try val.floatCast(sema.arena, dest_type); |
| 9748 | error.Overflow => return sema.mod.fail( | 9790 | return try sema.addConstant(dest_type, result_val); |
| 9791 | }, | ||
| 9792 | .Float => { | ||
| 9793 | const result_val = try val.floatCast(sema.arena, dest_type); | ||
| 9794 | if (!val.eql(result_val, dest_type)) { | ||
| 9795 | return sema.mod.fail( | ||
| 9749 | &block.base, | 9796 | &block.base, |
| 9750 | inst_src, | 9797 | inst_src, |
| 9751 | "cast of value {} to type '{}' loses information", | 9798 | "type {} cannot represent float value {}", |
| 9752 | .{ val, dest_type }, | 9799 | .{ dest_type, val }, |
| 9753 | ), | 9800 | ); |
| 9754 | error.OutOfMemory => return error.OutOfMemory, | 9801 | } |
| 9755 | }; | 9802 | return try sema.addConstant(dest_type, result_val); |
| 9756 | return try sema.addConstant(dest_type, res); | 9803 | }, |
| 9757 | } else if (src_zig_tag == .Int or src_zig_tag == .ComptimeInt) { | 9804 | .Int, .ComptimeInt => { |
| 9758 | const result_val = try val.intToFloat(sema.arena, dest_type, target); | 9805 | const result_val = try val.intToFloat(sema.arena, dest_type, target); |
| 9806 | // TODO implement this compile error | ||
| 9807 | //const int_again_val = try result_val.floatToInt(sema.arena, inst_ty); | ||
| 9808 | //if (!int_again_val.eql(val, inst_ty)) { | ||
| 9809 | // return sema.mod.fail( | ||
| 9810 | // &block.base, | ||
| 9811 | // inst_src, | ||
| 9812 | // "type {} cannot represent integer value {}", | ||
| 9813 | // .{ dest_type, val }, | ||
| 9814 | // ); | ||
| 9815 | //} | ||
| 9759 | return try sema.addConstant(dest_type, result_val); | 9816 | return try sema.addConstant(dest_type, result_val); |
| 9760 | } | 9817 | }, |
| 9818 | else => {}, | ||
| 9761 | }, | 9819 | }, |
| 9762 | else => {}, | 9820 | else => {}, |
| 9763 | } | 9821 | } |
src/Zir.zig+13-1| ... | @@ -319,9 +319,13 @@ pub const Inst = struct { | ... | @@ -319,9 +319,13 @@ pub const Inst = struct { |
| 319 | /// `error.Foo` syntax. Uses the `str_tok` field of the Data union. | 319 | /// `error.Foo` syntax. Uses the `str_tok` field of the Data union. |
| 320 | error_value, | 320 | error_value, |
| 321 | /// Implements the `@export` builtin function, based on either an identifier to a Decl, | 321 | /// Implements the `@export` builtin function, based on either an identifier to a Decl, |
| 322 | /// or field access of a Decl. | 322 | /// or field access of a Decl. The thing being exported is the Decl. |
| 323 | /// Uses the `pl_node` union field. Payload is `Export`. | 323 | /// Uses the `pl_node` union field. Payload is `Export`. |
| 324 | @"export", | 324 | @"export", |
| 325 | /// Implements the `@export` builtin function, based on a comptime-known value. | ||
| 326 | /// The thing being exported is the comptime-known value which is the operand. | ||
| 327 | /// Uses the `pl_node` union field. Payload is `ExportValue`. | ||
| 328 | export_value, | ||
| 325 | /// Given a pointer to a struct or object that contains virtual fields, returns a pointer | 329 | /// Given a pointer to a struct or object that contains virtual fields, returns a pointer |
| 326 | /// to the named field. The field name is stored in string_bytes. Used by a.b syntax. | 330 | /// to the named field. The field name is stored in string_bytes. Used by a.b syntax. |
| 327 | /// Uses `pl_node` field. The AST node is the a.b syntax. Payload is Field. | 331 | /// Uses `pl_node` field. The AST node is the a.b syntax. Payload is Field. |
| ... | @@ -1010,6 +1014,7 @@ pub const Inst = struct { | ... | @@ -1010,6 +1014,7 @@ pub const Inst = struct { |
| 1010 | .ensure_result_used, | 1014 | .ensure_result_used, |
| 1011 | .ensure_result_non_error, | 1015 | .ensure_result_non_error, |
| 1012 | .@"export", | 1016 | .@"export", |
| 1017 | .export_value, | ||
| 1013 | .field_ptr, | 1018 | .field_ptr, |
| 1014 | .field_val, | 1019 | .field_val, |
| 1015 | .field_ptr_named, | 1020 | .field_ptr_named, |
| ... | @@ -1273,6 +1278,7 @@ pub const Inst = struct { | ... | @@ -1273,6 +1278,7 @@ pub const Inst = struct { |
| 1273 | .error_union_type = .pl_node, | 1278 | .error_union_type = .pl_node, |
| 1274 | .error_value = .str_tok, | 1279 | .error_value = .str_tok, |
| 1275 | .@"export" = .pl_node, | 1280 | .@"export" = .pl_node, |
| 1281 | .export_value = .pl_node, | ||
| 1276 | .field_ptr = .pl_node, | 1282 | .field_ptr = .pl_node, |
| 1277 | .field_val = .pl_node, | 1283 | .field_val = .pl_node, |
| 1278 | .field_ptr_named = .pl_node, | 1284 | .field_ptr_named = .pl_node, |
| ... | @@ -2843,6 +2849,12 @@ pub const Inst = struct { | ... | @@ -2843,6 +2849,12 @@ pub const Inst = struct { |
| 2843 | options: Ref, | 2849 | options: Ref, |
| 2844 | }; | 2850 | }; |
| 2845 | 2851 | ||
| 2852 | pub const ExportValue = struct { | ||
| 2853 | /// The comptime value to export. | ||
| 2854 | operand: Ref, | ||
| 2855 | options: Ref, | ||
| 2856 | }; | ||
| 2857 | |||
| 2846 | /// Trailing: `CompileErrors.Item` for each `items_len`. | 2858 | /// Trailing: `CompileErrors.Item` for each `items_len`. |
| 2847 | pub const CompileErrors = struct { | 2859 | pub const CompileErrors = struct { |
| 2848 | items_len: u32, | 2860 | items_len: u32, |
src/codegen.zig+12-3| ... | @@ -859,7 +859,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -859,7 +859,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 859 | .call => try self.airCall(inst), | 859 | .call => try self.airCall(inst), |
| 860 | .cond_br => try self.airCondBr(inst), | 860 | .cond_br => try self.airCondBr(inst), |
| 861 | .dbg_stmt => try self.airDbgStmt(inst), | 861 | .dbg_stmt => try self.airDbgStmt(inst), |
| 862 | .floatcast => try self.airFloatCast(inst), | 862 | .fptrunc => try self.airFptrunc(inst), |
| 863 | .fpext => try self.airFpext(inst), | ||
| 863 | .intcast => try self.airIntCast(inst), | 864 | .intcast => try self.airIntCast(inst), |
| 864 | .trunc => try self.airTrunc(inst), | 865 | .trunc => try self.airTrunc(inst), |
| 865 | .bool_to_int => try self.airBoolToInt(inst), | 866 | .bool_to_int => try self.airBoolToInt(inst), |
| ... | @@ -1172,10 +1173,18 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -1172,10 +1173,18 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1172 | return self.finishAir(inst, .{ .ptr_stack_offset = stack_offset }, .{ .none, .none, .none }); | 1173 | return self.finishAir(inst, .{ .ptr_stack_offset = stack_offset }, .{ .none, .none, .none }); |
| 1173 | } | 1174 | } |
| 1174 | 1175 | ||
| 1175 | fn airFloatCast(self: *Self, inst: Air.Inst.Index) !void { | 1176 | fn airFptrunc(self: *Self, inst: Air.Inst.Index) !void { |
| 1176 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 1177 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 1177 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else switch (arch) { | 1178 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else switch (arch) { |
| 1178 | else => return self.fail("TODO implement floatCast for {}", .{self.target.cpu.arch}), | 1179 | else => return self.fail("TODO implement airFptrunc for {}", .{self.target.cpu.arch}), |
| 1180 | }; | ||
| 1181 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | ||
| 1182 | } | ||
| 1183 | |||
| 1184 | fn airFpext(self: *Self, inst: Air.Inst.Index) !void { | ||
| 1185 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | ||
| 1186 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else switch (arch) { | ||
| 1187 | else => return self.fail("TODO implement airFpext for {}", .{self.target.cpu.arch}), | ||
| 1179 | }; | 1188 | }; |
| 1180 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | 1189 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 1181 | } | 1190 | } |
src/codegen/c.zig+6-4| ... | @@ -954,7 +954,12 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO | ... | @@ -954,7 +954,12 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO |
| 954 | .atomic_rmw => try airAtomicRmw(f, inst), | 954 | .atomic_rmw => try airAtomicRmw(f, inst), |
| 955 | .atomic_load => try airAtomicLoad(f, inst), | 955 | .atomic_load => try airAtomicLoad(f, inst), |
| 956 | 956 | ||
| 957 | .int_to_float, .float_to_int => try airSimpleCast(f, inst), | 957 | .int_to_float, |
| 958 | .float_to_int, | ||
| 959 | .fptrunc, | ||
| 960 | .fpext, | ||
| 961 | .ptrtoint, | ||
| 962 | => try airSimpleCast(f, inst), | ||
| 958 | 963 | ||
| 959 | .atomic_store_unordered => try airAtomicStore(f, inst, toMemoryOrder(.Unordered)), | 964 | .atomic_store_unordered => try airAtomicStore(f, inst, toMemoryOrder(.Unordered)), |
| 960 | .atomic_store_monotonic => try airAtomicStore(f, inst, toMemoryOrder(.Monotonic)), | 965 | .atomic_store_monotonic => try airAtomicStore(f, inst, toMemoryOrder(.Monotonic)), |
| ... | @@ -982,9 +987,6 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO | ... | @@ -982,9 +987,6 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO |
| 982 | .unwrap_errunion_err_ptr => try airUnwrapErrUnionErr(f, inst), | 987 | .unwrap_errunion_err_ptr => try airUnwrapErrUnionErr(f, inst), |
| 983 | .wrap_errunion_payload => try airWrapErrUnionPay(f, inst), | 988 | .wrap_errunion_payload => try airWrapErrUnionPay(f, inst), |
| 984 | .wrap_errunion_err => try airWrapErrUnionErr(f, inst), | 989 | .wrap_errunion_err => try airWrapErrUnionErr(f, inst), |
| 985 | |||
| 986 | .ptrtoint => return f.fail("TODO: C backend: implement codegen for ptrtoint", .{}), | ||
| 987 | .floatcast => return f.fail("TODO: C backend: implement codegen for floatcast", .{}), | ||
| 988 | // zig fmt: on | 990 | // zig fmt: on |
| 989 | }; | 991 | }; |
| 990 | switch (result_value) { | 992 | switch (result_value) { |
src/codegen/llvm.zig+31-5| ... | @@ -472,7 +472,18 @@ pub const Object = struct { | ... | @@ -472,7 +472,18 @@ pub const Object = struct { |
| 472 | alias.setAliasee(llvm_fn); | 472 | alias.setAliasee(llvm_fn); |
| 473 | } else { | 473 | } else { |
| 474 | const alias = self.llvm_module.addAlias(llvm_fn.typeOf(), llvm_fn, exp_name_z); | 474 | const alias = self.llvm_module.addAlias(llvm_fn.typeOf(), llvm_fn, exp_name_z); |
| 475 | _ = alias; | 475 | switch (exp.options.linkage) { |
| 476 | .Internal => alias.setLinkage(.Internal), | ||
| 477 | .Strong => alias.setLinkage(.External), | ||
| 478 | .Weak => { | ||
| 479 | if (is_extern) { | ||
| 480 | alias.setLinkage(.ExternalWeak); | ||
| 481 | } else { | ||
| 482 | alias.setLinkage(.WeakODR); | ||
| 483 | } | ||
| 484 | }, | ||
| 485 | .LinkOnce => alias.setLinkage(.LinkOnceODR), | ||
| 486 | } | ||
| 476 | } | 487 | } |
| 477 | } | 488 | } |
| 478 | } | 489 | } |
| ... | @@ -1137,7 +1148,8 @@ pub const FuncGen = struct { | ... | @@ -1137,7 +1148,8 @@ pub const FuncGen = struct { |
| 1137 | .cond_br => try self.airCondBr(inst), | 1148 | .cond_br => try self.airCondBr(inst), |
| 1138 | .intcast => try self.airIntCast(inst), | 1149 | .intcast => try self.airIntCast(inst), |
| 1139 | .trunc => try self.airTrunc(inst), | 1150 | .trunc => try self.airTrunc(inst), |
| 1140 | .floatcast => try self.airFloatCast(inst), | 1151 | .fptrunc => try self.airFptrunc(inst), |
| 1152 | .fpext => try self.airFpext(inst), | ||
| 1141 | .ptrtoint => try self.airPtrToInt(inst), | 1153 | .ptrtoint => try self.airPtrToInt(inst), |
| 1142 | .load => try self.airLoad(inst), | 1154 | .load => try self.airLoad(inst), |
| 1143 | .loop => try self.airLoop(inst), | 1155 | .loop => try self.airLoop(inst), |
| ... | @@ -2060,12 +2072,26 @@ pub const FuncGen = struct { | ... | @@ -2060,12 +2072,26 @@ pub const FuncGen = struct { |
| 2060 | return self.builder.buildTrunc(operand, dest_llvm_ty, ""); | 2072 | return self.builder.buildTrunc(operand, dest_llvm_ty, ""); |
| 2061 | } | 2073 | } |
| 2062 | 2074 | ||
| 2063 | fn airFloatCast(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { | 2075 | fn airFptrunc(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { |
| 2064 | if (self.liveness.isUnused(inst)) | 2076 | if (self.liveness.isUnused(inst)) |
| 2065 | return null; | 2077 | return null; |
| 2066 | 2078 | ||
| 2067 | // TODO split floatcast AIR into float_widen and float_shorten | 2079 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 2068 | return self.todo("implement 'airFloatCast'", .{}); | 2080 | const operand = try self.resolveInst(ty_op.operand); |
| 2081 | const dest_llvm_ty = try self.dg.llvmType(self.air.typeOfIndex(inst)); | ||
| 2082 | |||
| 2083 | return self.builder.buildFPTrunc(operand, dest_llvm_ty, ""); | ||
| 2084 | } | ||
| 2085 | |||
| 2086 | fn airFpext(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { | ||
| 2087 | if (self.liveness.isUnused(inst)) | ||
| 2088 | return null; | ||
| 2089 | |||
| 2090 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | ||
| 2091 | const operand = try self.resolveInst(ty_op.operand); | ||
| 2092 | const dest_llvm_ty = try self.dg.llvmType(self.air.typeOfIndex(inst)); | ||
| 2093 | |||
| 2094 | return self.builder.buildFPExt(operand, dest_llvm_ty, ""); | ||
| 2069 | } | 2095 | } |
| 2070 | 2096 | ||
| 2071 | fn airPtrToInt(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { | 2097 | fn airPtrToInt(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { |
src/codegen/llvm/bindings.zig+16| ... | @@ -601,6 +601,22 @@ pub const Builder = opaque { | ... | @@ -601,6 +601,22 @@ pub const Builder = opaque { |
| 601 | DestTy: *const Type, | 601 | DestTy: *const Type, |
| 602 | Name: [*:0]const u8, | 602 | Name: [*:0]const u8, |
| 603 | ) *const Value; | 603 | ) *const Value; |
| 604 | |||
| 605 | pub const buildFPTrunc = LLVMBuildFPTrunc; | ||
| 606 | extern fn LLVMBuildFPTrunc( | ||
| 607 | *const Builder, | ||
| 608 | Val: *const Value, | ||
| 609 | DestTy: *const Type, | ||
| 610 | Name: [*:0]const u8, | ||
| 611 | ) *const Value; | ||
| 612 | |||
| 613 | pub const buildFPExt = LLVMBuildFPExt; | ||
| 614 | extern fn LLVMBuildFPExt( | ||
| 615 | *const Builder, | ||
| 616 | Val: *const Value, | ||
| 617 | DestTy: *const Type, | ||
| 618 | Name: [*:0]const u8, | ||
| 619 | ) *const Value; | ||
| 604 | }; | 620 | }; |
| 605 | 621 | ||
| 606 | pub const IntPredicate = enum(c_uint) { | 622 | pub const IntPredicate = enum(c_uint) { |
src/print_air.zig+2-1| ... | @@ -156,7 +156,8 @@ const Writer = struct { | ... | @@ -156,7 +156,8 @@ const Writer = struct { |
| 156 | .not, | 156 | .not, |
| 157 | .bitcast, | 157 | .bitcast, |
| 158 | .load, | 158 | .load, |
| 159 | .floatcast, | 159 | .fptrunc, |
| 160 | .fpext, | ||
| 160 | .intcast, | 161 | .intcast, |
| 161 | .trunc, | 162 | .trunc, |
| 162 | .optional_payload, | 163 | .optional_payload, |
src/print_zir.zig+12| ... | @@ -285,6 +285,7 @@ const Writer = struct { | ... | @@ -285,6 +285,7 @@ const Writer = struct { |
| 285 | => try self.writePlNodeBin(stream, inst), | 285 | => try self.writePlNodeBin(stream, inst), |
| 286 | 286 | ||
| 287 | .@"export" => try self.writePlNodeExport(stream, inst), | 287 | .@"export" => try self.writePlNodeExport(stream, inst), |
| 288 | .export_value => try self.writePlNodeExportValue(stream, inst), | ||
| 288 | 289 | ||
| 289 | .call, | 290 | .call, |
| 290 | .call_chkused, | 291 | .call_chkused, |
| ... | @@ -611,6 +612,17 @@ const Writer = struct { | ... | @@ -611,6 +612,17 @@ const Writer = struct { |
| 611 | try self.writeSrc(stream, inst_data.src()); | 612 | try self.writeSrc(stream, inst_data.src()); |
| 612 | } | 613 | } |
| 613 | 614 | ||
| 615 | fn writePlNodeExportValue(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { | ||
| 616 | const inst_data = self.code.instructions.items(.data)[inst].pl_node; | ||
| 617 | const extra = self.code.extraData(Zir.Inst.ExportValue, inst_data.payload_index).data; | ||
| 618 | |||
| 619 | try self.writeInstRef(stream, extra.operand); | ||
| 620 | try stream.writeAll(", "); | ||
| 621 | try self.writeInstRef(stream, extra.options); | ||
| 622 | try stream.writeAll(") "); | ||
| 623 | try self.writeSrc(stream, inst_data.src()); | ||
| 624 | } | ||
| 625 | |||
| 614 | fn writeStructInit(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { | 626 | fn writeStructInit(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { |
| 615 | const inst_data = self.code.instructions.items(.data)[inst].pl_node; | 627 | const inst_data = self.code.instructions.items(.data)[inst].pl_node; |
| 616 | const extra = self.code.extraData(Zir.Inst.StructInit, inst_data.payload_index); | 628 | const extra = self.code.extraData(Zir.Inst.StructInit, inst_data.payload_index); |
src/stage1/codegen.cpp+1| ... | @@ -9325,6 +9325,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) { | ... | @@ -9325,6 +9325,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) { |
| 9325 | buf_appendf(contents, "pub const single_threaded = %s;\n", bool_to_str(g->is_single_threaded)); | 9325 | buf_appendf(contents, "pub const single_threaded = %s;\n", bool_to_str(g->is_single_threaded)); |
| 9326 | buf_appendf(contents, "pub const abi = std.Target.Abi.%s;\n", cur_abi); | 9326 | buf_appendf(contents, "pub const abi = std.Target.Abi.%s;\n", cur_abi); |
| 9327 | buf_appendf(contents, "pub const cpu = std.Target.Cpu.baseline(.%s);\n", cur_arch); | 9327 | buf_appendf(contents, "pub const cpu = std.Target.Cpu.baseline(.%s);\n", cur_arch); |
| 9328 | buf_appendf(contents, "pub const stage2_arch: std.Target.Cpu.Arch = .%s;\n", cur_arch); | ||
| 9328 | buf_appendf(contents, "pub const os = std.Target.Os.Tag.defaultVersionRange(.%s);\n", cur_os); | 9329 | buf_appendf(contents, "pub const os = std.Target.Os.Tag.defaultVersionRange(.%s);\n", cur_os); |
| 9329 | buf_appendf(contents, | 9330 | buf_appendf(contents, |
| 9330 | "pub const target = std.Target{\n" | 9331 | "pub const target = std.Target{\n" |
src/value.zig+7-22| ... | @@ -1041,30 +1041,15 @@ pub const Value = extern union { | ... | @@ -1041,30 +1041,15 @@ pub const Value = extern union { |
| 1041 | } | 1041 | } |
| 1042 | } | 1042 | } |
| 1043 | 1043 | ||
| 1044 | /// Converts an integer or a float to a float. | 1044 | /// Converts an integer or a float to a float. May result in a loss of information. |
| 1045 | /// Returns `error.Overflow` if the value does not fit in the new type. | 1045 | /// Caller can find out by equality checking the result against the operand. |
| 1046 | pub fn floatCast(self: Value, allocator: *Allocator, dest_ty: Type) !Value { | 1046 | pub fn floatCast(self: Value, arena: *Allocator, dest_ty: Type) !Value { |
| 1047 | switch (dest_ty.tag()) { | 1047 | switch (dest_ty.tag()) { |
| 1048 | .f16 => { | 1048 | .f16 => return Value.Tag.float_16.create(arena, self.toFloat(f16)), |
| 1049 | const res = try Value.Tag.float_16.create(allocator, self.toFloat(f16)); | 1049 | .f32 => return Value.Tag.float_32.create(arena, self.toFloat(f32)), |
| 1050 | if (!self.eql(res, dest_ty)) | 1050 | .f64 => return Value.Tag.float_64.create(arena, self.toFloat(f64)), |
| 1051 | return error.Overflow; | ||
| 1052 | return res; | ||
| 1053 | }, | ||
| 1054 | .f32 => { | ||
| 1055 | const res = try Value.Tag.float_32.create(allocator, self.toFloat(f32)); | ||
| 1056 | if (!self.eql(res, dest_ty)) | ||
| 1057 | return error.Overflow; | ||
| 1058 | return res; | ||
| 1059 | }, | ||
| 1060 | .f64 => { | ||
| 1061 | const res = try Value.Tag.float_64.create(allocator, self.toFloat(f64)); | ||
| 1062 | if (!self.eql(res, dest_ty)) | ||
| 1063 | return error.Overflow; | ||
| 1064 | return res; | ||
| 1065 | }, | ||
| 1066 | .f128, .comptime_float, .c_longdouble => { | 1051 | .f128, .comptime_float, .c_longdouble => { |
| 1067 | return Value.Tag.float_128.create(allocator, self.toFloat(f128)); | 1052 | return Value.Tag.float_128.create(arena, self.toFloat(f128)); |
| 1068 | }, | 1053 | }, |
| 1069 | else => unreachable, | 1054 | else => unreachable, |
| 1070 | } | 1055 | } |
test/behavior.zig+2-2| ... | @@ -13,6 +13,7 @@ test { | ... | @@ -13,6 +13,7 @@ test { |
| 13 | _ = @import("behavior/atomics.zig"); | 13 | _ = @import("behavior/atomics.zig"); |
| 14 | _ = @import("behavior/sizeof_and_typeof.zig"); | 14 | _ = @import("behavior/sizeof_and_typeof.zig"); |
| 15 | _ = @import("behavior/translate_c_macros.zig"); | 15 | _ = @import("behavior/translate_c_macros.zig"); |
| 16 | _ = @import("behavior/union.zig"); | ||
| 16 | _ = @import("behavior/widening.zig"); | 17 | _ = @import("behavior/widening.zig"); |
| 17 | 18 | ||
| 18 | if (builtin.zig_is_stage2) { | 19 | if (builtin.zig_is_stage2) { |
| ... | @@ -149,7 +150,7 @@ test { | ... | @@ -149,7 +150,7 @@ test { |
| 149 | _ = @import("behavior/typename.zig"); | 150 | _ = @import("behavior/typename.zig"); |
| 150 | _ = @import("behavior/undefined.zig"); | 151 | _ = @import("behavior/undefined.zig"); |
| 151 | _ = @import("behavior/underscore.zig"); | 152 | _ = @import("behavior/underscore.zig"); |
| 152 | _ = @import("behavior/union.zig"); | 153 | _ = @import("behavior/union_stage1.zig"); |
| 153 | _ = @import("behavior/usingnamespace_stage1.zig"); | 154 | _ = @import("behavior/usingnamespace_stage1.zig"); |
| 154 | _ = @import("behavior/var_args.zig"); | 155 | _ = @import("behavior/var_args.zig"); |
| 155 | _ = @import("behavior/vector.zig"); | 156 | _ = @import("behavior/vector.zig"); |
| ... | @@ -158,7 +159,6 @@ test { | ... | @@ -158,7 +159,6 @@ test { |
| 158 | _ = @import("behavior/wasm.zig"); | 159 | _ = @import("behavior/wasm.zig"); |
| 159 | } | 160 | } |
| 160 | _ = @import("behavior/while.zig"); | 161 | _ = @import("behavior/while.zig"); |
| 161 | _ = @import("behavior/widening_stage1.zig"); | ||
| 162 | _ = @import("behavior/src.zig"); | 162 | _ = @import("behavior/src.zig"); |
| 163 | _ = @import("behavior/translate_c_macros_stage1.zig"); | 163 | _ = @import("behavior/translate_c_macros_stage1.zig"); |
| 164 | } | 164 | } |
test/behavior/union.zig-813| ... | @@ -2,816 +2,3 @@ const std = @import("std"); | ... | @@ -2,816 +2,3 @@ const std = @import("std"); |
| 2 | const expect = std.testing.expect; | 2 | const expect = std.testing.expect; |
| 3 | const expectEqual = std.testing.expectEqual; | 3 | const expectEqual = std.testing.expectEqual; |
| 4 | const Tag = std.meta.Tag; | 4 | const Tag = std.meta.Tag; |
| 5 | |||
| 6 | const Value = union(enum) { | ||
| 7 | Int: u64, | ||
| 8 | Array: [9]u8, | ||
| 9 | }; | ||
| 10 | |||
| 11 | const Agg = struct { | ||
| 12 | val1: Value, | ||
| 13 | val2: Value, | ||
| 14 | }; | ||
| 15 | |||
| 16 | const v1 = Value{ .Int = 1234 }; | ||
| 17 | const v2 = Value{ .Array = [_]u8{3} ** 9 }; | ||
| 18 | |||
| 19 | const err = @as(anyerror!Agg, Agg{ | ||
| 20 | .val1 = v1, | ||
| 21 | .val2 = v2, | ||
| 22 | }); | ||
| 23 | |||
| 24 | const array = [_]Value{ | ||
| 25 | v1, | ||
| 26 | v2, | ||
| 27 | v1, | ||
| 28 | v2, | ||
| 29 | }; | ||
| 30 | |||
| 31 | test "unions embedded in aggregate types" { | ||
| 32 | switch (array[1]) { | ||
| 33 | Value.Array => |arr| try expect(arr[4] == 3), | ||
| 34 | else => unreachable, | ||
| 35 | } | ||
| 36 | switch ((err catch unreachable).val1) { | ||
| 37 | Value.Int => |x| try expect(x == 1234), | ||
| 38 | else => unreachable, | ||
| 39 | } | ||
| 40 | } | ||
| 41 | |||
| 42 | const Foo = union { | ||
| 43 | float: f64, | ||
| 44 | int: i32, | ||
| 45 | }; | ||
| 46 | |||
| 47 | test "basic unions" { | ||
| 48 | var foo = Foo{ .int = 1 }; | ||
| 49 | try expect(foo.int == 1); | ||
| 50 | foo = Foo{ .float = 12.34 }; | ||
| 51 | try expect(foo.float == 12.34); | ||
| 52 | } | ||
| 53 | |||
| 54 | test "comptime union field access" { | ||
| 55 | comptime { | ||
| 56 | var foo = Foo{ .int = 0 }; | ||
| 57 | try expect(foo.int == 0); | ||
| 58 | |||
| 59 | foo = Foo{ .float = 42.42 }; | ||
| 60 | try expect(foo.float == 42.42); | ||
| 61 | } | ||
| 62 | } | ||
| 63 | |||
| 64 | test "init union with runtime value" { | ||
| 65 | var foo: Foo = undefined; | ||
| 66 | |||
| 67 | setFloat(&foo, 12.34); | ||
| 68 | try expect(foo.float == 12.34); | ||
| 69 | |||
| 70 | setInt(&foo, 42); | ||
| 71 | try expect(foo.int == 42); | ||
| 72 | } | ||
| 73 | |||
| 74 | fn setFloat(foo: *Foo, x: f64) void { | ||
| 75 | foo.* = Foo{ .float = x }; | ||
| 76 | } | ||
| 77 | |||
| 78 | fn setInt(foo: *Foo, x: i32) void { | ||
| 79 | foo.* = Foo{ .int = x }; | ||
| 80 | } | ||
| 81 | |||
| 82 | const FooExtern = extern union { | ||
| 83 | float: f64, | ||
| 84 | int: i32, | ||
| 85 | }; | ||
| 86 | |||
| 87 | test "basic extern unions" { | ||
| 88 | var foo = FooExtern{ .int = 1 }; | ||
| 89 | try expect(foo.int == 1); | ||
| 90 | foo.float = 12.34; | ||
| 91 | try expect(foo.float == 12.34); | ||
| 92 | } | ||
| 93 | |||
| 94 | const Letter = enum { | ||
| 95 | A, | ||
| 96 | B, | ||
| 97 | C, | ||
| 98 | }; | ||
| 99 | const Payload = union(Letter) { | ||
| 100 | A: i32, | ||
| 101 | B: f64, | ||
| 102 | C: bool, | ||
| 103 | }; | ||
| 104 | |||
| 105 | test "union with specified enum tag" { | ||
| 106 | try doTest(); | ||
| 107 | comptime try doTest(); | ||
| 108 | } | ||
| 109 | |||
| 110 | fn doTest() error{TestUnexpectedResult}!void { | ||
| 111 | try expect((try bar(Payload{ .A = 1234 })) == -10); | ||
| 112 | } | ||
| 113 | |||
| 114 | fn bar(value: Payload) error{TestUnexpectedResult}!i32 { | ||
| 115 | try expect(@as(Letter, value) == Letter.A); | ||
| 116 | return switch (value) { | ||
| 117 | Payload.A => |x| return x - 1244, | ||
| 118 | Payload.B => |x| if (x == 12.34) @as(i32, 20) else 21, | ||
| 119 | Payload.C => |x| if (x) @as(i32, 30) else 31, | ||
| 120 | }; | ||
| 121 | } | ||
| 122 | |||
| 123 | const MultipleChoice = union(enum(u32)) { | ||
| 124 | A = 20, | ||
| 125 | B = 40, | ||
| 126 | C = 60, | ||
| 127 | D = 1000, | ||
| 128 | }; | ||
| 129 | test "simple union(enum(u32))" { | ||
| 130 | var x = MultipleChoice.C; | ||
| 131 | try expect(x == MultipleChoice.C); | ||
| 132 | try expect(@enumToInt(@as(Tag(MultipleChoice), x)) == 60); | ||
| 133 | } | ||
| 134 | |||
| 135 | const MultipleChoice2 = union(enum(u32)) { | ||
| 136 | Unspecified1: i32, | ||
| 137 | A: f32 = 20, | ||
| 138 | Unspecified2: void, | ||
| 139 | B: bool = 40, | ||
| 140 | Unspecified3: i32, | ||
| 141 | C: i8 = 60, | ||
| 142 | Unspecified4: void, | ||
| 143 | D: void = 1000, | ||
| 144 | Unspecified5: i32, | ||
| 145 | }; | ||
| 146 | |||
| 147 | test "union(enum(u32)) with specified and unspecified tag values" { | ||
| 148 | comptime try expect(Tag(Tag(MultipleChoice2)) == u32); | ||
| 149 | try testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2{ .C = 123 }); | ||
| 150 | comptime try testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2{ .C = 123 }); | ||
| 151 | } | ||
| 152 | |||
| 153 | fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) !void { | ||
| 154 | try expect(@enumToInt(@as(Tag(MultipleChoice2), x)) == 60); | ||
| 155 | try expect(1123 == switch (x) { | ||
| 156 | MultipleChoice2.A => 1, | ||
| 157 | MultipleChoice2.B => 2, | ||
| 158 | MultipleChoice2.C => |v| @as(i32, 1000) + v, | ||
| 159 | MultipleChoice2.D => 4, | ||
| 160 | MultipleChoice2.Unspecified1 => 5, | ||
| 161 | MultipleChoice2.Unspecified2 => 6, | ||
| 162 | MultipleChoice2.Unspecified3 => 7, | ||
| 163 | MultipleChoice2.Unspecified4 => 8, | ||
| 164 | MultipleChoice2.Unspecified5 => 9, | ||
| 165 | }); | ||
| 166 | } | ||
| 167 | |||
| 168 | const ExternPtrOrInt = extern union { | ||
| 169 | ptr: *u8, | ||
| 170 | int: u64, | ||
| 171 | }; | ||
| 172 | test "extern union size" { | ||
| 173 | comptime try expect(@sizeOf(ExternPtrOrInt) == 8); | ||
| 174 | } | ||
| 175 | |||
| 176 | const PackedPtrOrInt = packed union { | ||
| 177 | ptr: *u8, | ||
| 178 | int: u64, | ||
| 179 | }; | ||
| 180 | test "extern union size" { | ||
| 181 | comptime try expect(@sizeOf(PackedPtrOrInt) == 8); | ||
| 182 | } | ||
| 183 | |||
| 184 | const ZeroBits = union { | ||
| 185 | OnlyField: void, | ||
| 186 | }; | ||
| 187 | test "union with only 1 field which is void should be zero bits" { | ||
| 188 | comptime try expect(@sizeOf(ZeroBits) == 0); | ||
| 189 | } | ||
| 190 | |||
| 191 | const TheTag = enum { | ||
| 192 | A, | ||
| 193 | B, | ||
| 194 | C, | ||
| 195 | }; | ||
| 196 | const TheUnion = union(TheTag) { | ||
| 197 | A: i32, | ||
| 198 | B: i32, | ||
| 199 | C: i32, | ||
| 200 | }; | ||
| 201 | test "union field access gives the enum values" { | ||
| 202 | try expect(TheUnion.A == TheTag.A); | ||
| 203 | try expect(TheUnion.B == TheTag.B); | ||
| 204 | try expect(TheUnion.C == TheTag.C); | ||
| 205 | } | ||
| 206 | |||
| 207 | test "cast union to tag type of union" { | ||
| 208 | try testCastUnionToTag(TheUnion{ .B = 1234 }); | ||
| 209 | comptime try testCastUnionToTag(TheUnion{ .B = 1234 }); | ||
| 210 | } | ||
| 211 | |||
| 212 | fn testCastUnionToTag(x: TheUnion) !void { | ||
| 213 | try expect(@as(TheTag, x) == TheTag.B); | ||
| 214 | } | ||
| 215 | |||
| 216 | test "cast tag type of union to union" { | ||
| 217 | var x: Value2 = Letter2.B; | ||
| 218 | try expect(@as(Letter2, x) == Letter2.B); | ||
| 219 | } | ||
| 220 | const Letter2 = enum { | ||
| 221 | A, | ||
| 222 | B, | ||
| 223 | C, | ||
| 224 | }; | ||
| 225 | const Value2 = union(Letter2) { | ||
| 226 | A: i32, | ||
| 227 | B, | ||
| 228 | C, | ||
| 229 | }; | ||
| 230 | |||
| 231 | test "implicit cast union to its tag type" { | ||
| 232 | var x: Value2 = Letter2.B; | ||
| 233 | try expect(x == Letter2.B); | ||
| 234 | try giveMeLetterB(x); | ||
| 235 | } | ||
| 236 | fn giveMeLetterB(x: Letter2) !void { | ||
| 237 | try expect(x == Value2.B); | ||
| 238 | } | ||
| 239 | |||
| 240 | pub const PackThis = union(enum) { | ||
| 241 | Invalid: bool, | ||
| 242 | StringLiteral: u2, | ||
| 243 | }; | ||
| 244 | |||
| 245 | test "constant packed union" { | ||
| 246 | try testConstPackedUnion(&[_]PackThis{PackThis{ .StringLiteral = 1 }}); | ||
| 247 | } | ||
| 248 | |||
| 249 | fn testConstPackedUnion(expected_tokens: []const PackThis) !void { | ||
| 250 | try expect(expected_tokens[0].StringLiteral == 1); | ||
| 251 | } | ||
| 252 | |||
| 253 | test "switch on union with only 1 field" { | ||
| 254 | var r: PartialInst = undefined; | ||
| 255 | r = PartialInst.Compiled; | ||
| 256 | switch (r) { | ||
| 257 | PartialInst.Compiled => { | ||
| 258 | var z: PartialInstWithPayload = undefined; | ||
| 259 | z = PartialInstWithPayload{ .Compiled = 1234 }; | ||
| 260 | switch (z) { | ||
| 261 | PartialInstWithPayload.Compiled => |x| { | ||
| 262 | try expect(x == 1234); | ||
| 263 | return; | ||
| 264 | }, | ||
| 265 | } | ||
| 266 | }, | ||
| 267 | } | ||
| 268 | unreachable; | ||
| 269 | } | ||
| 270 | |||
| 271 | const PartialInst = union(enum) { | ||
| 272 | Compiled, | ||
| 273 | }; | ||
| 274 | |||
| 275 | const PartialInstWithPayload = union(enum) { | ||
| 276 | Compiled: i32, | ||
| 277 | }; | ||
| 278 | |||
| 279 | test "access a member of tagged union with conflicting enum tag name" { | ||
| 280 | const Bar = union(enum) { | ||
| 281 | A: A, | ||
| 282 | B: B, | ||
| 283 | |||
| 284 | const A = u8; | ||
| 285 | const B = void; | ||
| 286 | }; | ||
| 287 | |||
| 288 | comptime try expect(Bar.A == u8); | ||
| 289 | } | ||
| 290 | |||
| 291 | test "tagged union initialization with runtime void" { | ||
| 292 | try expect(testTaggedUnionInit({})); | ||
| 293 | } | ||
| 294 | |||
| 295 | const TaggedUnionWithAVoid = union(enum) { | ||
| 296 | A, | ||
| 297 | B: i32, | ||
| 298 | }; | ||
| 299 | |||
| 300 | fn testTaggedUnionInit(x: anytype) bool { | ||
| 301 | const y = TaggedUnionWithAVoid{ .A = x }; | ||
| 302 | return @as(Tag(TaggedUnionWithAVoid), y) == TaggedUnionWithAVoid.A; | ||
| 303 | } | ||
| 304 | |||
| 305 | pub const UnionEnumNoPayloads = union(enum) { | ||
| 306 | A, | ||
| 307 | B, | ||
| 308 | }; | ||
| 309 | |||
| 310 | test "tagged union with no payloads" { | ||
| 311 | const a = UnionEnumNoPayloads{ .B = {} }; | ||
| 312 | switch (a) { | ||
| 313 | Tag(UnionEnumNoPayloads).A => @panic("wrong"), | ||
| 314 | Tag(UnionEnumNoPayloads).B => {}, | ||
| 315 | } | ||
| 316 | } | ||
| 317 | |||
| 318 | test "union with only 1 field casted to its enum type" { | ||
| 319 | const Literal = union(enum) { | ||
| 320 | Number: f64, | ||
| 321 | Bool: bool, | ||
| 322 | }; | ||
| 323 | |||
| 324 | const Expr = union(enum) { | ||
| 325 | Literal: Literal, | ||
| 326 | }; | ||
| 327 | |||
| 328 | var e = Expr{ .Literal = Literal{ .Bool = true } }; | ||
| 329 | const ExprTag = Tag(Expr); | ||
| 330 | comptime try expect(Tag(ExprTag) == u0); | ||
| 331 | var t = @as(ExprTag, e); | ||
| 332 | try expect(t == Expr.Literal); | ||
| 333 | } | ||
| 334 | |||
| 335 | test "union with only 1 field casted to its enum type which has enum value specified" { | ||
| 336 | const Literal = union(enum) { | ||
| 337 | Number: f64, | ||
| 338 | Bool: bool, | ||
| 339 | }; | ||
| 340 | |||
| 341 | const ExprTag = enum(comptime_int) { | ||
| 342 | Literal = 33, | ||
| 343 | }; | ||
| 344 | |||
| 345 | const Expr = union(ExprTag) { | ||
| 346 | Literal: Literal, | ||
| 347 | }; | ||
| 348 | |||
| 349 | var e = Expr{ .Literal = Literal{ .Bool = true } }; | ||
| 350 | comptime try expect(Tag(ExprTag) == comptime_int); | ||
| 351 | var t = @as(ExprTag, e); | ||
| 352 | try expect(t == Expr.Literal); | ||
| 353 | try expect(@enumToInt(t) == 33); | ||
| 354 | comptime try expect(@enumToInt(t) == 33); | ||
| 355 | } | ||
| 356 | |||
| 357 | test "@enumToInt works on unions" { | ||
| 358 | const Bar = union(enum) { | ||
| 359 | A: bool, | ||
| 360 | B: u8, | ||
| 361 | C, | ||
| 362 | }; | ||
| 363 | |||
| 364 | const a = Bar{ .A = true }; | ||
| 365 | var b = Bar{ .B = undefined }; | ||
| 366 | var c = Bar.C; | ||
| 367 | try expect(@enumToInt(a) == 0); | ||
| 368 | try expect(@enumToInt(b) == 1); | ||
| 369 | try expect(@enumToInt(c) == 2); | ||
| 370 | } | ||
| 371 | |||
| 372 | const Attribute = union(enum) { | ||
| 373 | A: bool, | ||
| 374 | B: u8, | ||
| 375 | }; | ||
| 376 | |||
| 377 | fn setAttribute(attr: Attribute) void { | ||
| 378 | _ = attr; | ||
| 379 | } | ||
| 380 | |||
| 381 | fn Setter(attr: Attribute) type { | ||
| 382 | return struct { | ||
| 383 | fn set() void { | ||
| 384 | setAttribute(attr); | ||
| 385 | } | ||
| 386 | }; | ||
| 387 | } | ||
| 388 | |||
| 389 | test "comptime union field value equality" { | ||
| 390 | const a0 = Setter(Attribute{ .A = false }); | ||
| 391 | const a1 = Setter(Attribute{ .A = true }); | ||
| 392 | const a2 = Setter(Attribute{ .A = false }); | ||
| 393 | |||
| 394 | const b0 = Setter(Attribute{ .B = 5 }); | ||
| 395 | const b1 = Setter(Attribute{ .B = 9 }); | ||
| 396 | const b2 = Setter(Attribute{ .B = 5 }); | ||
| 397 | |||
| 398 | try expect(a0 == a0); | ||
| 399 | try expect(a1 == a1); | ||
| 400 | try expect(a0 == a2); | ||
| 401 | |||
| 402 | try expect(b0 == b0); | ||
| 403 | try expect(b1 == b1); | ||
| 404 | try expect(b0 == b2); | ||
| 405 | |||
| 406 | try expect(a0 != b0); | ||
| 407 | try expect(a0 != a1); | ||
| 408 | try expect(b0 != b1); | ||
| 409 | } | ||
| 410 | |||
| 411 | test "return union init with void payload" { | ||
| 412 | const S = struct { | ||
| 413 | fn entry() !void { | ||
| 414 | try expect(func().state == State.one); | ||
| 415 | } | ||
| 416 | const Outer = union(enum) { | ||
| 417 | state: State, | ||
| 418 | }; | ||
| 419 | const State = union(enum) { | ||
| 420 | one: void, | ||
| 421 | two: u32, | ||
| 422 | }; | ||
| 423 | fn func() Outer { | ||
| 424 | return Outer{ .state = State{ .one = {} } }; | ||
| 425 | } | ||
| 426 | }; | ||
| 427 | try S.entry(); | ||
| 428 | comptime try S.entry(); | ||
| 429 | } | ||
| 430 | |||
| 431 | test "@unionInit can modify a union type" { | ||
| 432 | const UnionInitEnum = union(enum) { | ||
| 433 | Boolean: bool, | ||
| 434 | Byte: u8, | ||
| 435 | }; | ||
| 436 | |||
| 437 | var value: UnionInitEnum = undefined; | ||
| 438 | |||
| 439 | value = @unionInit(UnionInitEnum, "Boolean", true); | ||
| 440 | try expect(value.Boolean == true); | ||
| 441 | value.Boolean = false; | ||
| 442 | try expect(value.Boolean == false); | ||
| 443 | |||
| 444 | value = @unionInit(UnionInitEnum, "Byte", 2); | ||
| 445 | try expect(value.Byte == 2); | ||
| 446 | value.Byte = 3; | ||
| 447 | try expect(value.Byte == 3); | ||
| 448 | } | ||
| 449 | |||
| 450 | test "@unionInit can modify a pointer value" { | ||
| 451 | const UnionInitEnum = union(enum) { | ||
| 452 | Boolean: bool, | ||
| 453 | Byte: u8, | ||
| 454 | }; | ||
| 455 | |||
| 456 | var value: UnionInitEnum = undefined; | ||
| 457 | var value_ptr = &value; | ||
| 458 | |||
| 459 | value_ptr.* = @unionInit(UnionInitEnum, "Boolean", true); | ||
| 460 | try expect(value.Boolean == true); | ||
| 461 | |||
| 462 | value_ptr.* = @unionInit(UnionInitEnum, "Byte", 2); | ||
| 463 | try expect(value.Byte == 2); | ||
| 464 | } | ||
| 465 | |||
| 466 | test "union no tag with struct member" { | ||
| 467 | const Struct = struct {}; | ||
| 468 | const Union = union { | ||
| 469 | s: Struct, | ||
| 470 | pub fn foo(self: *@This()) void { | ||
| 471 | _ = self; | ||
| 472 | } | ||
| 473 | }; | ||
| 474 | var u = Union{ .s = Struct{} }; | ||
| 475 | u.foo(); | ||
| 476 | } | ||
| 477 | |||
| 478 | fn testComparison() !void { | ||
| 479 | var x = Payload{ .A = 42 }; | ||
| 480 | try expect(x == .A); | ||
| 481 | try expect(x != .B); | ||
| 482 | try expect(x != .C); | ||
| 483 | try expect((x == .B) == false); | ||
| 484 | try expect((x == .C) == false); | ||
| 485 | try expect((x != .A) == false); | ||
| 486 | } | ||
| 487 | |||
| 488 | test "comparison between union and enum literal" { | ||
| 489 | try testComparison(); | ||
| 490 | comptime try testComparison(); | ||
| 491 | } | ||
| 492 | |||
| 493 | test "packed union generates correctly aligned LLVM type" { | ||
| 494 | const U = packed union { | ||
| 495 | f1: fn () error{TestUnexpectedResult}!void, | ||
| 496 | f2: u32, | ||
| 497 | }; | ||
| 498 | var foo = [_]U{ | ||
| 499 | U{ .f1 = doTest }, | ||
| 500 | U{ .f2 = 0 }, | ||
| 501 | }; | ||
| 502 | try foo[0].f1(); | ||
| 503 | } | ||
| 504 | |||
| 505 | test "union with one member defaults to u0 tag type" { | ||
| 506 | const U0 = union(enum) { | ||
| 507 | X: u32, | ||
| 508 | }; | ||
| 509 | comptime try expect(Tag(Tag(U0)) == u0); | ||
| 510 | } | ||
| 511 | |||
| 512 | test "union with comptime_int tag" { | ||
| 513 | const Union = union(enum(comptime_int)) { | ||
| 514 | X: u32, | ||
| 515 | Y: u16, | ||
| 516 | Z: u8, | ||
| 517 | }; | ||
| 518 | comptime try expect(Tag(Tag(Union)) == comptime_int); | ||
| 519 | } | ||
| 520 | |||
| 521 | test "extern union doesn't trigger field check at comptime" { | ||
| 522 | const U = extern union { | ||
| 523 | x: u32, | ||
| 524 | y: u8, | ||
| 525 | }; | ||
| 526 | |||
| 527 | const x = U{ .x = 0x55AAAA55 }; | ||
| 528 | comptime try expect(x.y == 0x55); | ||
| 529 | } | ||
| 530 | |||
| 531 | const Foo1 = union(enum) { | ||
| 532 | f: struct { | ||
| 533 | x: usize, | ||
| 534 | }, | ||
| 535 | }; | ||
| 536 | var glbl: Foo1 = undefined; | ||
| 537 | |||
| 538 | test "global union with single field is correctly initialized" { | ||
| 539 | glbl = Foo1{ | ||
| 540 | .f = @typeInfo(Foo1).Union.fields[0].field_type{ .x = 123 }, | ||
| 541 | }; | ||
| 542 | try expect(glbl.f.x == 123); | ||
| 543 | } | ||
| 544 | |||
| 545 | pub const FooUnion = union(enum) { | ||
| 546 | U0: usize, | ||
| 547 | U1: u8, | ||
| 548 | }; | ||
| 549 | |||
| 550 | var glbl_array: [2]FooUnion = undefined; | ||
| 551 | |||
| 552 | test "initialize global array of union" { | ||
| 553 | glbl_array[1] = FooUnion{ .U1 = 2 }; | ||
| 554 | glbl_array[0] = FooUnion{ .U0 = 1 }; | ||
| 555 | try expect(glbl_array[0].U0 == 1); | ||
| 556 | try expect(glbl_array[1].U1 == 2); | ||
| 557 | } | ||
| 558 | |||
| 559 | test "anonymous union literal syntax" { | ||
| 560 | const S = struct { | ||
| 561 | const Number = union { | ||
| 562 | int: i32, | ||
| 563 | float: f64, | ||
| 564 | }; | ||
| 565 | |||
| 566 | fn doTheTest() !void { | ||
| 567 | var i: Number = .{ .int = 42 }; | ||
| 568 | var f = makeNumber(); | ||
| 569 | try expect(i.int == 42); | ||
| 570 | try expect(f.float == 12.34); | ||
| 571 | } | ||
| 572 | |||
| 573 | fn makeNumber() Number { | ||
| 574 | return .{ .float = 12.34 }; | ||
| 575 | } | ||
| 576 | }; | ||
| 577 | try S.doTheTest(); | ||
| 578 | comptime try S.doTheTest(); | ||
| 579 | } | ||
| 580 | |||
| 581 | test "update the tag value for zero-sized unions" { | ||
| 582 | const S = union(enum) { | ||
| 583 | U0: void, | ||
| 584 | U1: void, | ||
| 585 | }; | ||
| 586 | var x = S{ .U0 = {} }; | ||
| 587 | try expect(x == .U0); | ||
| 588 | x = S{ .U1 = {} }; | ||
| 589 | try expect(x == .U1); | ||
| 590 | } | ||
| 591 | |||
| 592 | test "function call result coerces from tagged union to the tag" { | ||
| 593 | const S = struct { | ||
| 594 | const Arch = union(enum) { | ||
| 595 | One, | ||
| 596 | Two: usize, | ||
| 597 | }; | ||
| 598 | |||
| 599 | const ArchTag = Tag(Arch); | ||
| 600 | |||
| 601 | fn doTheTest() !void { | ||
| 602 | var x: ArchTag = getArch1(); | ||
| 603 | try expect(x == .One); | ||
| 604 | |||
| 605 | var y: ArchTag = getArch2(); | ||
| 606 | try expect(y == .Two); | ||
| 607 | } | ||
| 608 | |||
| 609 | pub fn getArch1() Arch { | ||
| 610 | return .One; | ||
| 611 | } | ||
| 612 | |||
| 613 | pub fn getArch2() Arch { | ||
| 614 | return .{ .Two = 99 }; | ||
| 615 | } | ||
| 616 | }; | ||
| 617 | try S.doTheTest(); | ||
| 618 | comptime try S.doTheTest(); | ||
| 619 | } | ||
| 620 | |||
| 621 | test "0-sized extern union definition" { | ||
| 622 | const U = extern union { | ||
| 623 | a: void, | ||
| 624 | const f = 1; | ||
| 625 | }; | ||
| 626 | |||
| 627 | try expect(U.f == 1); | ||
| 628 | } | ||
| 629 | |||
| 630 | test "union initializer generates padding only if needed" { | ||
| 631 | const U = union(enum) { | ||
| 632 | A: u24, | ||
| 633 | }; | ||
| 634 | |||
| 635 | var v = U{ .A = 532 }; | ||
| 636 | try expect(v.A == 532); | ||
| 637 | } | ||
| 638 | |||
| 639 | test "runtime tag name with single field" { | ||
| 640 | const U = union(enum) { | ||
| 641 | A: i32, | ||
| 642 | }; | ||
| 643 | |||
| 644 | var v = U{ .A = 42 }; | ||
| 645 | try expect(std.mem.eql(u8, @tagName(v), "A")); | ||
| 646 | } | ||
| 647 | |||
| 648 | test "cast from anonymous struct to union" { | ||
| 649 | const S = struct { | ||
| 650 | const U = union(enum) { | ||
| 651 | A: u32, | ||
| 652 | B: []const u8, | ||
| 653 | C: void, | ||
| 654 | }; | ||
| 655 | fn doTheTest() !void { | ||
| 656 | var y: u32 = 42; | ||
| 657 | const t0 = .{ .A = 123 }; | ||
| 658 | const t1 = .{ .B = "foo" }; | ||
| 659 | const t2 = .{ .C = {} }; | ||
| 660 | const t3 = .{ .A = y }; | ||
| 661 | const x0: U = t0; | ||
| 662 | var x1: U = t1; | ||
| 663 | const x2: U = t2; | ||
| 664 | var x3: U = t3; | ||
| 665 | try expect(x0.A == 123); | ||
| 666 | try expect(std.mem.eql(u8, x1.B, "foo")); | ||
| 667 | try expect(x2 == .C); | ||
| 668 | try expect(x3.A == y); | ||
| 669 | } | ||
| 670 | }; | ||
| 671 | try S.doTheTest(); | ||
| 672 | comptime try S.doTheTest(); | ||
| 673 | } | ||
| 674 | |||
| 675 | test "cast from pointer to anonymous struct to pointer to union" { | ||
| 676 | const S = struct { | ||
| 677 | const U = union(enum) { | ||
| 678 | A: u32, | ||
| 679 | B: []const u8, | ||
| 680 | C: void, | ||
| 681 | }; | ||
| 682 | fn doTheTest() !void { | ||
| 683 | var y: u32 = 42; | ||
| 684 | const t0 = &.{ .A = 123 }; | ||
| 685 | const t1 = &.{ .B = "foo" }; | ||
| 686 | const t2 = &.{ .C = {} }; | ||
| 687 | const t3 = &.{ .A = y }; | ||
| 688 | const x0: *const U = t0; | ||
| 689 | var x1: *const U = t1; | ||
| 690 | const x2: *const U = t2; | ||
| 691 | var x3: *const U = t3; | ||
| 692 | try expect(x0.A == 123); | ||
| 693 | try expect(std.mem.eql(u8, x1.B, "foo")); | ||
| 694 | try expect(x2.* == .C); | ||
| 695 | try expect(x3.A == y); | ||
| 696 | } | ||
| 697 | }; | ||
| 698 | try S.doTheTest(); | ||
| 699 | comptime try S.doTheTest(); | ||
| 700 | } | ||
| 701 | |||
| 702 | test "method call on an empty union" { | ||
| 703 | const S = struct { | ||
| 704 | const MyUnion = union(MyUnionTag) { | ||
| 705 | pub const MyUnionTag = enum { X1, X2 }; | ||
| 706 | X1: [0]u8, | ||
| 707 | X2: [0]u8, | ||
| 708 | |||
| 709 | pub fn useIt(self: *@This()) bool { | ||
| 710 | _ = self; | ||
| 711 | return true; | ||
| 712 | } | ||
| 713 | }; | ||
| 714 | |||
| 715 | fn doTheTest() !void { | ||
| 716 | var u = MyUnion{ .X1 = [0]u8{} }; | ||
| 717 | try expect(u.useIt()); | ||
| 718 | } | ||
| 719 | }; | ||
| 720 | try S.doTheTest(); | ||
| 721 | comptime try S.doTheTest(); | ||
| 722 | } | ||
| 723 | |||
| 724 | test "switching on non exhaustive union" { | ||
| 725 | const S = struct { | ||
| 726 | const E = enum(u8) { | ||
| 727 | a, | ||
| 728 | b, | ||
| 729 | _, | ||
| 730 | }; | ||
| 731 | const U = union(E) { | ||
| 732 | a: i32, | ||
| 733 | b: u32, | ||
| 734 | }; | ||
| 735 | fn doTheTest() !void { | ||
| 736 | var a = U{ .a = 2 }; | ||
| 737 | switch (a) { | ||
| 738 | .a => |val| try expect(val == 2), | ||
| 739 | .b => unreachable, | ||
| 740 | } | ||
| 741 | } | ||
| 742 | }; | ||
| 743 | try S.doTheTest(); | ||
| 744 | comptime try S.doTheTest(); | ||
| 745 | } | ||
| 746 | |||
| 747 | test "containers with single-field enums" { | ||
| 748 | const S = struct { | ||
| 749 | const A = union(enum) { f1 }; | ||
| 750 | const B = union(enum) { f1: void }; | ||
| 751 | const C = struct { a: A }; | ||
| 752 | const D = struct { a: B }; | ||
| 753 | |||
| 754 | fn doTheTest() !void { | ||
| 755 | var array1 = [1]A{A{ .f1 = {} }}; | ||
| 756 | var array2 = [1]B{B{ .f1 = {} }}; | ||
| 757 | try expect(array1[0] == .f1); | ||
| 758 | try expect(array2[0] == .f1); | ||
| 759 | |||
| 760 | var struct1 = C{ .a = A{ .f1 = {} } }; | ||
| 761 | var struct2 = D{ .a = B{ .f1 = {} } }; | ||
| 762 | try expect(struct1.a == .f1); | ||
| 763 | try expect(struct2.a == .f1); | ||
| 764 | } | ||
| 765 | }; | ||
| 766 | |||
| 767 | try S.doTheTest(); | ||
| 768 | comptime try S.doTheTest(); | ||
| 769 | } | ||
| 770 | |||
| 771 | test "@unionInit on union w/ tag but no fields" { | ||
| 772 | const S = struct { | ||
| 773 | const Type = enum(u8) { no_op = 105 }; | ||
| 774 | |||
| 775 | const Data = union(Type) { | ||
| 776 | no_op: void, | ||
| 777 | |||
| 778 | pub fn decode(buf: []const u8) Data { | ||
| 779 | _ = buf; | ||
| 780 | return @unionInit(Data, "no_op", {}); | ||
| 781 | } | ||
| 782 | }; | ||
| 783 | |||
| 784 | comptime { | ||
| 785 | std.debug.assert(@sizeOf(Data) != 0); | ||
| 786 | } | ||
| 787 | |||
| 788 | fn doTheTest() !void { | ||
| 789 | var data: Data = .{ .no_op = .{} }; | ||
| 790 | _ = data; | ||
| 791 | var o = Data.decode(&[_]u8{}); | ||
| 792 | try expectEqual(Type.no_op, o); | ||
| 793 | } | ||
| 794 | }; | ||
| 795 | |||
| 796 | try S.doTheTest(); | ||
| 797 | comptime try S.doTheTest(); | ||
| 798 | } | ||
| 799 | |||
| 800 | test "union enum type gets a separate scope" { | ||
| 801 | const S = struct { | ||
| 802 | const U = union(enum) { | ||
| 803 | a: u8, | ||
| 804 | const foo = 1; | ||
| 805 | }; | ||
| 806 | |||
| 807 | fn doTheTest() !void { | ||
| 808 | try expect(!@hasDecl(Tag(U), "foo")); | ||
| 809 | } | ||
| 810 | }; | ||
| 811 | |||
| 812 | try S.doTheTest(); | ||
| 813 | } | ||
| 814 | test "anytype union field: issue #9233" { | ||
| 815 | const Baz = union(enum) { bar: anytype }; | ||
| 816 | _ = Baz; | ||
| 817 | } |
test/behavior/union_stage1.zig created+799| ... | @@ -0,0 +1,799 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const expect = std.testing.expect; | ||
| 3 | const expectEqual = std.testing.expectEqual; | ||
| 4 | const Tag = std.meta.Tag; | ||
| 5 | |||
| 6 | const Value = union(enum) { | ||
| 7 | Int: u64, | ||
| 8 | Array: [9]u8, | ||
| 9 | }; | ||
| 10 | |||
| 11 | const Agg = struct { | ||
| 12 | val1: Value, | ||
| 13 | val2: Value, | ||
| 14 | }; | ||
| 15 | |||
| 16 | const v1 = Value{ .Int = 1234 }; | ||
| 17 | const v2 = Value{ .Array = [_]u8{3} ** 9 }; | ||
| 18 | |||
| 19 | const err = @as(anyerror!Agg, Agg{ | ||
| 20 | .val1 = v1, | ||
| 21 | .val2 = v2, | ||
| 22 | }); | ||
| 23 | |||
| 24 | const array = [_]Value{ v1, v2, v1, v2 }; | ||
| 25 | |||
| 26 | test "unions embedded in aggregate types" { | ||
| 27 | switch (array[1]) { | ||
| 28 | Value.Array => |arr| try expect(arr[4] == 3), | ||
| 29 | else => unreachable, | ||
| 30 | } | ||
| 31 | switch ((err catch unreachable).val1) { | ||
| 32 | Value.Int => |x| try expect(x == 1234), | ||
| 33 | else => unreachable, | ||
| 34 | } | ||
| 35 | } | ||
| 36 | |||
| 37 | const Foo = union { | ||
| 38 | float: f64, | ||
| 39 | int: i32, | ||
| 40 | }; | ||
| 41 | |||
| 42 | test "basic unions" { | ||
| 43 | var foo = Foo{ .int = 1 }; | ||
| 44 | try expect(foo.int == 1); | ||
| 45 | foo = Foo{ .float = 12.34 }; | ||
| 46 | try expect(foo.float == 12.34); | ||
| 47 | } | ||
| 48 | |||
| 49 | test "comptime union field access" { | ||
| 50 | comptime { | ||
| 51 | var foo = Foo{ .int = 0 }; | ||
| 52 | try expect(foo.int == 0); | ||
| 53 | |||
| 54 | foo = Foo{ .float = 42.42 }; | ||
| 55 | try expect(foo.float == 42.42); | ||
| 56 | } | ||
| 57 | } | ||
| 58 | |||
| 59 | test "init union with runtime value" { | ||
| 60 | var foo: Foo = undefined; | ||
| 61 | |||
| 62 | setFloat(&foo, 12.34); | ||
| 63 | try expect(foo.float == 12.34); | ||
| 64 | |||
| 65 | setInt(&foo, 42); | ||
| 66 | try expect(foo.int == 42); | ||
| 67 | } | ||
| 68 | |||
| 69 | fn setFloat(foo: *Foo, x: f64) void { | ||
| 70 | foo.* = Foo{ .float = x }; | ||
| 71 | } | ||
| 72 | |||
| 73 | fn setInt(foo: *Foo, x: i32) void { | ||
| 74 | foo.* = Foo{ .int = x }; | ||
| 75 | } | ||
| 76 | |||
| 77 | const FooExtern = extern union { | ||
| 78 | float: f64, | ||
| 79 | int: i32, | ||
| 80 | }; | ||
| 81 | |||
| 82 | test "basic extern unions" { | ||
| 83 | var foo = FooExtern{ .int = 1 }; | ||
| 84 | try expect(foo.int == 1); | ||
| 85 | foo.float = 12.34; | ||
| 86 | try expect(foo.float == 12.34); | ||
| 87 | } | ||
| 88 | |||
| 89 | const Letter = enum { A, B, C }; | ||
| 90 | const Payload = union(Letter) { | ||
| 91 | A: i32, | ||
| 92 | B: f64, | ||
| 93 | C: bool, | ||
| 94 | }; | ||
| 95 | |||
| 96 | test "union with specified enum tag" { | ||
| 97 | try doTest(); | ||
| 98 | comptime try doTest(); | ||
| 99 | } | ||
| 100 | |||
| 101 | fn doTest() error{TestUnexpectedResult}!void { | ||
| 102 | try expect((try bar(Payload{ .A = 1234 })) == -10); | ||
| 103 | } | ||
| 104 | |||
| 105 | fn bar(value: Payload) error{TestUnexpectedResult}!i32 { | ||
| 106 | try expect(@as(Letter, value) == Letter.A); | ||
| 107 | return switch (value) { | ||
| 108 | Payload.A => |x| return x - 1244, | ||
| 109 | Payload.B => |x| if (x == 12.34) @as(i32, 20) else 21, | ||
| 110 | Payload.C => |x| if (x) @as(i32, 30) else 31, | ||
| 111 | }; | ||
| 112 | } | ||
| 113 | |||
| 114 | const MultipleChoice = union(enum(u32)) { | ||
| 115 | A = 20, | ||
| 116 | B = 40, | ||
| 117 | C = 60, | ||
| 118 | D = 1000, | ||
| 119 | }; | ||
| 120 | test "simple union(enum(u32))" { | ||
| 121 | var x = MultipleChoice.C; | ||
| 122 | try expect(x == MultipleChoice.C); | ||
| 123 | try expect(@enumToInt(@as(Tag(MultipleChoice), x)) == 60); | ||
| 124 | } | ||
| 125 | |||
| 126 | const MultipleChoice2 = union(enum(u32)) { | ||
| 127 | Unspecified1: i32, | ||
| 128 | A: f32 = 20, | ||
| 129 | Unspecified2: void, | ||
| 130 | B: bool = 40, | ||
| 131 | Unspecified3: i32, | ||
| 132 | C: i8 = 60, | ||
| 133 | Unspecified4: void, | ||
| 134 | D: void = 1000, | ||
| 135 | Unspecified5: i32, | ||
| 136 | }; | ||
| 137 | |||
| 138 | test "union(enum(u32)) with specified and unspecified tag values" { | ||
| 139 | comptime try expect(Tag(Tag(MultipleChoice2)) == u32); | ||
| 140 | try testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2{ .C = 123 }); | ||
| 141 | comptime try testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2{ .C = 123 }); | ||
| 142 | } | ||
| 143 | |||
| 144 | fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) !void { | ||
| 145 | try expect(@enumToInt(@as(Tag(MultipleChoice2), x)) == 60); | ||
| 146 | try expect(1123 == switch (x) { | ||
| 147 | MultipleChoice2.A => 1, | ||
| 148 | MultipleChoice2.B => 2, | ||
| 149 | MultipleChoice2.C => |v| @as(i32, 1000) + v, | ||
| 150 | MultipleChoice2.D => 4, | ||
| 151 | MultipleChoice2.Unspecified1 => 5, | ||
| 152 | MultipleChoice2.Unspecified2 => 6, | ||
| 153 | MultipleChoice2.Unspecified3 => 7, | ||
| 154 | MultipleChoice2.Unspecified4 => 8, | ||
| 155 | MultipleChoice2.Unspecified5 => 9, | ||
| 156 | }); | ||
| 157 | } | ||
| 158 | |||
| 159 | const ExternPtrOrInt = extern union { | ||
| 160 | ptr: *u8, | ||
| 161 | int: u64, | ||
| 162 | }; | ||
| 163 | test "extern union size" { | ||
| 164 | comptime try expect(@sizeOf(ExternPtrOrInt) == 8); | ||
| 165 | } | ||
| 166 | |||
| 167 | const PackedPtrOrInt = packed union { | ||
| 168 | ptr: *u8, | ||
| 169 | int: u64, | ||
| 170 | }; | ||
| 171 | test "extern union size" { | ||
| 172 | comptime try expect(@sizeOf(PackedPtrOrInt) == 8); | ||
| 173 | } | ||
| 174 | |||
| 175 | const ZeroBits = union { | ||
| 176 | OnlyField: void, | ||
| 177 | }; | ||
| 178 | test "union with only 1 field which is void should be zero bits" { | ||
| 179 | comptime try expect(@sizeOf(ZeroBits) == 0); | ||
| 180 | } | ||
| 181 | |||
| 182 | const TheTag = enum { A, B, C }; | ||
| 183 | const TheUnion = union(TheTag) { | ||
| 184 | A: i32, | ||
| 185 | B: i32, | ||
| 186 | C: i32, | ||
| 187 | }; | ||
| 188 | test "union field access gives the enum values" { | ||
| 189 | try expect(TheUnion.A == TheTag.A); | ||
| 190 | try expect(TheUnion.B == TheTag.B); | ||
| 191 | try expect(TheUnion.C == TheTag.C); | ||
| 192 | } | ||
| 193 | |||
| 194 | test "cast union to tag type of union" { | ||
| 195 | try testCastUnionToTag(TheUnion{ .B = 1234 }); | ||
| 196 | comptime try testCastUnionToTag(TheUnion{ .B = 1234 }); | ||
| 197 | } | ||
| 198 | |||
| 199 | fn testCastUnionToTag(x: TheUnion) !void { | ||
| 200 | try expect(@as(TheTag, x) == TheTag.B); | ||
| 201 | } | ||
| 202 | |||
| 203 | test "cast tag type of union to union" { | ||
| 204 | var x: Value2 = Letter2.B; | ||
| 205 | try expect(@as(Letter2, x) == Letter2.B); | ||
| 206 | } | ||
| 207 | const Letter2 = enum { A, B, C }; | ||
| 208 | const Value2 = union(Letter2) { | ||
| 209 | A: i32, | ||
| 210 | B, | ||
| 211 | C, | ||
| 212 | }; | ||
| 213 | |||
| 214 | test "implicit cast union to its tag type" { | ||
| 215 | var x: Value2 = Letter2.B; | ||
| 216 | try expect(x == Letter2.B); | ||
| 217 | try giveMeLetterB(x); | ||
| 218 | } | ||
| 219 | fn giveMeLetterB(x: Letter2) !void { | ||
| 220 | try expect(x == Value2.B); | ||
| 221 | } | ||
| 222 | |||
| 223 | // TODO it looks like this test intended to test packed unions, but this is not a packed | ||
| 224 | // union. go through git history and find out what happened. | ||
| 225 | pub const PackThis = union(enum) { | ||
| 226 | Invalid: bool, | ||
| 227 | StringLiteral: u2, | ||
| 228 | }; | ||
| 229 | |||
| 230 | test "constant packed union" { | ||
| 231 | try testConstPackedUnion(&[_]PackThis{PackThis{ .StringLiteral = 1 }}); | ||
| 232 | } | ||
| 233 | |||
| 234 | fn testConstPackedUnion(expected_tokens: []const PackThis) !void { | ||
| 235 | try expect(expected_tokens[0].StringLiteral == 1); | ||
| 236 | } | ||
| 237 | |||
| 238 | test "switch on union with only 1 field" { | ||
| 239 | var r: PartialInst = undefined; | ||
| 240 | r = PartialInst.Compiled; | ||
| 241 | switch (r) { | ||
| 242 | PartialInst.Compiled => { | ||
| 243 | var z: PartialInstWithPayload = undefined; | ||
| 244 | z = PartialInstWithPayload{ .Compiled = 1234 }; | ||
| 245 | switch (z) { | ||
| 246 | PartialInstWithPayload.Compiled => |x| { | ||
| 247 | try expect(x == 1234); | ||
| 248 | return; | ||
| 249 | }, | ||
| 250 | } | ||
| 251 | }, | ||
| 252 | } | ||
| 253 | unreachable; | ||
| 254 | } | ||
| 255 | |||
| 256 | const PartialInst = union(enum) { | ||
| 257 | Compiled, | ||
| 258 | }; | ||
| 259 | |||
| 260 | const PartialInstWithPayload = union(enum) { | ||
| 261 | Compiled: i32, | ||
| 262 | }; | ||
| 263 | |||
| 264 | test "access a member of tagged union with conflicting enum tag name" { | ||
| 265 | const Bar = union(enum) { | ||
| 266 | A: A, | ||
| 267 | B: B, | ||
| 268 | |||
| 269 | const A = u8; | ||
| 270 | const B = void; | ||
| 271 | }; | ||
| 272 | |||
| 273 | comptime try expect(Bar.A == u8); | ||
| 274 | } | ||
| 275 | |||
| 276 | test "tagged union initialization with runtime void" { | ||
| 277 | try expect(testTaggedUnionInit({})); | ||
| 278 | } | ||
| 279 | |||
| 280 | const TaggedUnionWithAVoid = union(enum) { | ||
| 281 | A, | ||
| 282 | B: i32, | ||
| 283 | }; | ||
| 284 | |||
| 285 | fn testTaggedUnionInit(x: anytype) bool { | ||
| 286 | const y = TaggedUnionWithAVoid{ .A = x }; | ||
| 287 | return @as(Tag(TaggedUnionWithAVoid), y) == TaggedUnionWithAVoid.A; | ||
| 288 | } | ||
| 289 | |||
| 290 | pub const UnionEnumNoPayloads = union(enum) { A, B }; | ||
| 291 | |||
| 292 | test "tagged union with no payloads" { | ||
| 293 | const a = UnionEnumNoPayloads{ .B = {} }; | ||
| 294 | switch (a) { | ||
| 295 | Tag(UnionEnumNoPayloads).A => @panic("wrong"), | ||
| 296 | Tag(UnionEnumNoPayloads).B => {}, | ||
| 297 | } | ||
| 298 | } | ||
| 299 | |||
| 300 | test "union with only 1 field casted to its enum type" { | ||
| 301 | const Literal = union(enum) { | ||
| 302 | Number: f64, | ||
| 303 | Bool: bool, | ||
| 304 | }; | ||
| 305 | |||
| 306 | const Expr = union(enum) { | ||
| 307 | Literal: Literal, | ||
| 308 | }; | ||
| 309 | |||
| 310 | var e = Expr{ .Literal = Literal{ .Bool = true } }; | ||
| 311 | const ExprTag = Tag(Expr); | ||
| 312 | comptime try expect(Tag(ExprTag) == u0); | ||
| 313 | var t = @as(ExprTag, e); | ||
| 314 | try expect(t == Expr.Literal); | ||
| 315 | } | ||
| 316 | |||
| 317 | test "union with only 1 field casted to its enum type which has enum value specified" { | ||
| 318 | const Literal = union(enum) { | ||
| 319 | Number: f64, | ||
| 320 | Bool: bool, | ||
| 321 | }; | ||
| 322 | |||
| 323 | const ExprTag = enum(comptime_int) { | ||
| 324 | Literal = 33, | ||
| 325 | }; | ||
| 326 | |||
| 327 | const Expr = union(ExprTag) { | ||
| 328 | Literal: Literal, | ||
| 329 | }; | ||
| 330 | |||
| 331 | var e = Expr{ .Literal = Literal{ .Bool = true } }; | ||
| 332 | comptime try expect(Tag(ExprTag) == comptime_int); | ||
| 333 | var t = @as(ExprTag, e); | ||
| 334 | try expect(t == Expr.Literal); | ||
| 335 | try expect(@enumToInt(t) == 33); | ||
| 336 | comptime try expect(@enumToInt(t) == 33); | ||
| 337 | } | ||
| 338 | |||
| 339 | test "@enumToInt works on unions" { | ||
| 340 | const Bar = union(enum) { | ||
| 341 | A: bool, | ||
| 342 | B: u8, | ||
| 343 | C, | ||
| 344 | }; | ||
| 345 | |||
| 346 | const a = Bar{ .A = true }; | ||
| 347 | var b = Bar{ .B = undefined }; | ||
| 348 | var c = Bar.C; | ||
| 349 | try expect(@enumToInt(a) == 0); | ||
| 350 | try expect(@enumToInt(b) == 1); | ||
| 351 | try expect(@enumToInt(c) == 2); | ||
| 352 | } | ||
| 353 | |||
| 354 | const Attribute = union(enum) { | ||
| 355 | A: bool, | ||
| 356 | B: u8, | ||
| 357 | }; | ||
| 358 | |||
| 359 | fn setAttribute(attr: Attribute) void { | ||
| 360 | _ = attr; | ||
| 361 | } | ||
| 362 | |||
| 363 | fn Setter(attr: Attribute) type { | ||
| 364 | return struct { | ||
| 365 | fn set() void { | ||
| 366 | setAttribute(attr); | ||
| 367 | } | ||
| 368 | }; | ||
| 369 | } | ||
| 370 | |||
| 371 | test "comptime union field value equality" { | ||
| 372 | const a0 = Setter(Attribute{ .A = false }); | ||
| 373 | const a1 = Setter(Attribute{ .A = true }); | ||
| 374 | const a2 = Setter(Attribute{ .A = false }); | ||
| 375 | |||
| 376 | const b0 = Setter(Attribute{ .B = 5 }); | ||
| 377 | const b1 = Setter(Attribute{ .B = 9 }); | ||
| 378 | const b2 = Setter(Attribute{ .B = 5 }); | ||
| 379 | |||
| 380 | try expect(a0 == a0); | ||
| 381 | try expect(a1 == a1); | ||
| 382 | try expect(a0 == a2); | ||
| 383 | |||
| 384 | try expect(b0 == b0); | ||
| 385 | try expect(b1 == b1); | ||
| 386 | try expect(b0 == b2); | ||
| 387 | |||
| 388 | try expect(a0 != b0); | ||
| 389 | try expect(a0 != a1); | ||
| 390 | try expect(b0 != b1); | ||
| 391 | } | ||
| 392 | |||
| 393 | test "return union init with void payload" { | ||
| 394 | const S = struct { | ||
| 395 | fn entry() !void { | ||
| 396 | try expect(func().state == State.one); | ||
| 397 | } | ||
| 398 | const Outer = union(enum) { | ||
| 399 | state: State, | ||
| 400 | }; | ||
| 401 | const State = union(enum) { | ||
| 402 | one: void, | ||
| 403 | two: u32, | ||
| 404 | }; | ||
| 405 | fn func() Outer { | ||
| 406 | return Outer{ .state = State{ .one = {} } }; | ||
| 407 | } | ||
| 408 | }; | ||
| 409 | try S.entry(); | ||
| 410 | comptime try S.entry(); | ||
| 411 | } | ||
| 412 | |||
| 413 | test "@unionInit can modify a union type" { | ||
| 414 | const UnionInitEnum = union(enum) { | ||
| 415 | Boolean: bool, | ||
| 416 | Byte: u8, | ||
| 417 | }; | ||
| 418 | |||
| 419 | var value: UnionInitEnum = undefined; | ||
| 420 | |||
| 421 | value = @unionInit(UnionInitEnum, "Boolean", true); | ||
| 422 | try expect(value.Boolean == true); | ||
| 423 | value.Boolean = false; | ||
| 424 | try expect(value.Boolean == false); | ||
| 425 | |||
| 426 | value = @unionInit(UnionInitEnum, "Byte", 2); | ||
| 427 | try expect(value.Byte == 2); | ||
| 428 | value.Byte = 3; | ||
| 429 | try expect(value.Byte == 3); | ||
| 430 | } | ||
| 431 | |||
| 432 | test "@unionInit can modify a pointer value" { | ||
| 433 | const UnionInitEnum = union(enum) { | ||
| 434 | Boolean: bool, | ||
| 435 | Byte: u8, | ||
| 436 | }; | ||
| 437 | |||
| 438 | var value: UnionInitEnum = undefined; | ||
| 439 | var value_ptr = &value; | ||
| 440 | |||
| 441 | value_ptr.* = @unionInit(UnionInitEnum, "Boolean", true); | ||
| 442 | try expect(value.Boolean == true); | ||
| 443 | |||
| 444 | value_ptr.* = @unionInit(UnionInitEnum, "Byte", 2); | ||
| 445 | try expect(value.Byte == 2); | ||
| 446 | } | ||
| 447 | |||
| 448 | test "union no tag with struct member" { | ||
| 449 | const Struct = struct {}; | ||
| 450 | const Union = union { | ||
| 451 | s: Struct, | ||
| 452 | pub fn foo(self: *@This()) void { | ||
| 453 | _ = self; | ||
| 454 | } | ||
| 455 | }; | ||
| 456 | var u = Union{ .s = Struct{} }; | ||
| 457 | u.foo(); | ||
| 458 | } | ||
| 459 | |||
| 460 | fn testComparison() !void { | ||
| 461 | var x = Payload{ .A = 42 }; | ||
| 462 | try expect(x == .A); | ||
| 463 | try expect(x != .B); | ||
| 464 | try expect(x != .C); | ||
| 465 | try expect((x == .B) == false); | ||
| 466 | try expect((x == .C) == false); | ||
| 467 | try expect((x != .A) == false); | ||
| 468 | } | ||
| 469 | |||
| 470 | test "comparison between union and enum literal" { | ||
| 471 | try testComparison(); | ||
| 472 | comptime try testComparison(); | ||
| 473 | } | ||
| 474 | |||
| 475 | test "packed union generates correctly aligned LLVM type" { | ||
| 476 | const U = packed union { | ||
| 477 | f1: fn () error{TestUnexpectedResult}!void, | ||
| 478 | f2: u32, | ||
| 479 | }; | ||
| 480 | var foo = [_]U{ | ||
| 481 | U{ .f1 = doTest }, | ||
| 482 | U{ .f2 = 0 }, | ||
| 483 | }; | ||
| 484 | try foo[0].f1(); | ||
| 485 | } | ||
| 486 | |||
| 487 | test "union with one member defaults to u0 tag type" { | ||
| 488 | const U0 = union(enum) { | ||
| 489 | X: u32, | ||
| 490 | }; | ||
| 491 | comptime try expect(Tag(Tag(U0)) == u0); | ||
| 492 | } | ||
| 493 | |||
| 494 | test "union with comptime_int tag" { | ||
| 495 | const Union = union(enum(comptime_int)) { | ||
| 496 | X: u32, | ||
| 497 | Y: u16, | ||
| 498 | Z: u8, | ||
| 499 | }; | ||
| 500 | comptime try expect(Tag(Tag(Union)) == comptime_int); | ||
| 501 | } | ||
| 502 | |||
| 503 | test "extern union doesn't trigger field check at comptime" { | ||
| 504 | const U = extern union { | ||
| 505 | x: u32, | ||
| 506 | y: u8, | ||
| 507 | }; | ||
| 508 | |||
| 509 | const x = U{ .x = 0x55AAAA55 }; | ||
| 510 | comptime try expect(x.y == 0x55); | ||
| 511 | } | ||
| 512 | |||
| 513 | const Foo1 = union(enum) { | ||
| 514 | f: struct { | ||
| 515 | x: usize, | ||
| 516 | }, | ||
| 517 | }; | ||
| 518 | var glbl: Foo1 = undefined; | ||
| 519 | |||
| 520 | test "global union with single field is correctly initialized" { | ||
| 521 | glbl = Foo1{ | ||
| 522 | .f = @typeInfo(Foo1).Union.fields[0].field_type{ .x = 123 }, | ||
| 523 | }; | ||
| 524 | try expect(glbl.f.x == 123); | ||
| 525 | } | ||
| 526 | |||
| 527 | pub const FooUnion = union(enum) { | ||
| 528 | U0: usize, | ||
| 529 | U1: u8, | ||
| 530 | }; | ||
| 531 | |||
| 532 | var glbl_array: [2]FooUnion = undefined; | ||
| 533 | |||
| 534 | test "initialize global array of union" { | ||
| 535 | glbl_array[1] = FooUnion{ .U1 = 2 }; | ||
| 536 | glbl_array[0] = FooUnion{ .U0 = 1 }; | ||
| 537 | try expect(glbl_array[0].U0 == 1); | ||
| 538 | try expect(glbl_array[1].U1 == 2); | ||
| 539 | } | ||
| 540 | |||
| 541 | test "anonymous union literal syntax" { | ||
| 542 | const S = struct { | ||
| 543 | const Number = union { | ||
| 544 | int: i32, | ||
| 545 | float: f64, | ||
| 546 | }; | ||
| 547 | |||
| 548 | fn doTheTest() !void { | ||
| 549 | var i: Number = .{ .int = 42 }; | ||
| 550 | var f = makeNumber(); | ||
| 551 | try expect(i.int == 42); | ||
| 552 | try expect(f.float == 12.34); | ||
| 553 | } | ||
| 554 | |||
| 555 | fn makeNumber() Number { | ||
| 556 | return .{ .float = 12.34 }; | ||
| 557 | } | ||
| 558 | }; | ||
| 559 | try S.doTheTest(); | ||
| 560 | comptime try S.doTheTest(); | ||
| 561 | } | ||
| 562 | |||
| 563 | test "update the tag value for zero-sized unions" { | ||
| 564 | const S = union(enum) { | ||
| 565 | U0: void, | ||
| 566 | U1: void, | ||
| 567 | }; | ||
| 568 | var x = S{ .U0 = {} }; | ||
| 569 | try expect(x == .U0); | ||
| 570 | x = S{ .U1 = {} }; | ||
| 571 | try expect(x == .U1); | ||
| 572 | } | ||
| 573 | |||
| 574 | test "function call result coerces from tagged union to the tag" { | ||
| 575 | const S = struct { | ||
| 576 | const Arch = union(enum) { | ||
| 577 | One, | ||
| 578 | Two: usize, | ||
| 579 | }; | ||
| 580 | |||
| 581 | const ArchTag = Tag(Arch); | ||
| 582 | |||
| 583 | fn doTheTest() !void { | ||
| 584 | var x: ArchTag = getArch1(); | ||
| 585 | try expect(x == .One); | ||
| 586 | |||
| 587 | var y: ArchTag = getArch2(); | ||
| 588 | try expect(y == .Two); | ||
| 589 | } | ||
| 590 | |||
| 591 | pub fn getArch1() Arch { | ||
| 592 | return .One; | ||
| 593 | } | ||
| 594 | |||
| 595 | pub fn getArch2() Arch { | ||
| 596 | return .{ .Two = 99 }; | ||
| 597 | } | ||
| 598 | }; | ||
| 599 | try S.doTheTest(); | ||
| 600 | comptime try S.doTheTest(); | ||
| 601 | } | ||
| 602 | |||
| 603 | test "0-sized extern union definition" { | ||
| 604 | const U = extern union { | ||
| 605 | a: void, | ||
| 606 | const f = 1; | ||
| 607 | }; | ||
| 608 | |||
| 609 | try expect(U.f == 1); | ||
| 610 | } | ||
| 611 | |||
| 612 | test "union initializer generates padding only if needed" { | ||
| 613 | const U = union(enum) { | ||
| 614 | A: u24, | ||
| 615 | }; | ||
| 616 | |||
| 617 | var v = U{ .A = 532 }; | ||
| 618 | try expect(v.A == 532); | ||
| 619 | } | ||
| 620 | |||
| 621 | test "runtime tag name with single field" { | ||
| 622 | const U = union(enum) { | ||
| 623 | A: i32, | ||
| 624 | }; | ||
| 625 | |||
| 626 | var v = U{ .A = 42 }; | ||
| 627 | try expect(std.mem.eql(u8, @tagName(v), "A")); | ||
| 628 | } | ||
| 629 | |||
| 630 | test "cast from anonymous struct to union" { | ||
| 631 | const S = struct { | ||
| 632 | const U = union(enum) { | ||
| 633 | A: u32, | ||
| 634 | B: []const u8, | ||
| 635 | C: void, | ||
| 636 | }; | ||
| 637 | fn doTheTest() !void { | ||
| 638 | var y: u32 = 42; | ||
| 639 | const t0 = .{ .A = 123 }; | ||
| 640 | const t1 = .{ .B = "foo" }; | ||
| 641 | const t2 = .{ .C = {} }; | ||
| 642 | const t3 = .{ .A = y }; | ||
| 643 | const x0: U = t0; | ||
| 644 | var x1: U = t1; | ||
| 645 | const x2: U = t2; | ||
| 646 | var x3: U = t3; | ||
| 647 | try expect(x0.A == 123); | ||
| 648 | try expect(std.mem.eql(u8, x1.B, "foo")); | ||
| 649 | try expect(x2 == .C); | ||
| 650 | try expect(x3.A == y); | ||
| 651 | } | ||
| 652 | }; | ||
| 653 | try S.doTheTest(); | ||
| 654 | comptime try S.doTheTest(); | ||
| 655 | } | ||
| 656 | |||
| 657 | test "cast from pointer to anonymous struct to pointer to union" { | ||
| 658 | const S = struct { | ||
| 659 | const U = union(enum) { | ||
| 660 | A: u32, | ||
| 661 | B: []const u8, | ||
| 662 | C: void, | ||
| 663 | }; | ||
| 664 | fn doTheTest() !void { | ||
| 665 | var y: u32 = 42; | ||
| 666 | const t0 = &.{ .A = 123 }; | ||
| 667 | const t1 = &.{ .B = "foo" }; | ||
| 668 | const t2 = &.{ .C = {} }; | ||
| 669 | const t3 = &.{ .A = y }; | ||
| 670 | const x0: *const U = t0; | ||
| 671 | var x1: *const U = t1; | ||
| 672 | const x2: *const U = t2; | ||
| 673 | var x3: *const U = t3; | ||
| 674 | try expect(x0.A == 123); | ||
| 675 | try expect(std.mem.eql(u8, x1.B, "foo")); | ||
| 676 | try expect(x2.* == .C); | ||
| 677 | try expect(x3.A == y); | ||
| 678 | } | ||
| 679 | }; | ||
| 680 | try S.doTheTest(); | ||
| 681 | comptime try S.doTheTest(); | ||
| 682 | } | ||
| 683 | |||
| 684 | test "method call on an empty union" { | ||
| 685 | const S = struct { | ||
| 686 | const MyUnion = union(MyUnionTag) { | ||
| 687 | pub const MyUnionTag = enum { X1, X2 }; | ||
| 688 | X1: [0]u8, | ||
| 689 | X2: [0]u8, | ||
| 690 | |||
| 691 | pub fn useIt(self: *@This()) bool { | ||
| 692 | _ = self; | ||
| 693 | return true; | ||
| 694 | } | ||
| 695 | }; | ||
| 696 | |||
| 697 | fn doTheTest() !void { | ||
| 698 | var u = MyUnion{ .X1 = [0]u8{} }; | ||
| 699 | try expect(u.useIt()); | ||
| 700 | } | ||
| 701 | }; | ||
| 702 | try S.doTheTest(); | ||
| 703 | comptime try S.doTheTest(); | ||
| 704 | } | ||
| 705 | |||
| 706 | test "switching on non exhaustive union" { | ||
| 707 | const S = struct { | ||
| 708 | const E = enum(u8) { | ||
| 709 | a, | ||
| 710 | b, | ||
| 711 | _, | ||
| 712 | }; | ||
| 713 | const U = union(E) { | ||
| 714 | a: i32, | ||
| 715 | b: u32, | ||
| 716 | }; | ||
| 717 | fn doTheTest() !void { | ||
| 718 | var a = U{ .a = 2 }; | ||
| 719 | switch (a) { | ||
| 720 | .a => |val| try expect(val == 2), | ||
| 721 | .b => unreachable, | ||
| 722 | } | ||
| 723 | } | ||
| 724 | }; | ||
| 725 | try S.doTheTest(); | ||
| 726 | comptime try S.doTheTest(); | ||
| 727 | } | ||
| 728 | |||
| 729 | test "containers with single-field enums" { | ||
| 730 | const S = struct { | ||
| 731 | const A = union(enum) { f1 }; | ||
| 732 | const B = union(enum) { f1: void }; | ||
| 733 | const C = struct { a: A }; | ||
| 734 | const D = struct { a: B }; | ||
| 735 | |||
| 736 | fn doTheTest() !void { | ||
| 737 | var array1 = [1]A{A{ .f1 = {} }}; | ||
| 738 | var array2 = [1]B{B{ .f1 = {} }}; | ||
| 739 | try expect(array1[0] == .f1); | ||
| 740 | try expect(array2[0] == .f1); | ||
| 741 | |||
| 742 | var struct1 = C{ .a = A{ .f1 = {} } }; | ||
| 743 | var struct2 = D{ .a = B{ .f1 = {} } }; | ||
| 744 | try expect(struct1.a == .f1); | ||
| 745 | try expect(struct2.a == .f1); | ||
| 746 | } | ||
| 747 | }; | ||
| 748 | |||
| 749 | try S.doTheTest(); | ||
| 750 | comptime try S.doTheTest(); | ||
| 751 | } | ||
| 752 | |||
| 753 | test "@unionInit on union w/ tag but no fields" { | ||
| 754 | const S = struct { | ||
| 755 | const Type = enum(u8) { no_op = 105 }; | ||
| 756 | |||
| 757 | const Data = union(Type) { | ||
| 758 | no_op: void, | ||
| 759 | |||
| 760 | pub fn decode(buf: []const u8) Data { | ||
| 761 | _ = buf; | ||
| 762 | return @unionInit(Data, "no_op", {}); | ||
| 763 | } | ||
| 764 | }; | ||
| 765 | |||
| 766 | comptime { | ||
| 767 | std.debug.assert(@sizeOf(Data) != 0); | ||
| 768 | } | ||
| 769 | |||
| 770 | fn doTheTest() !void { | ||
| 771 | var data: Data = .{ .no_op = .{} }; | ||
| 772 | _ = data; | ||
| 773 | var o = Data.decode(&[_]u8{}); | ||
| 774 | try expectEqual(Type.no_op, o); | ||
| 775 | } | ||
| 776 | }; | ||
| 777 | |||
| 778 | try S.doTheTest(); | ||
| 779 | comptime try S.doTheTest(); | ||
| 780 | } | ||
| 781 | |||
| 782 | test "union enum type gets a separate scope" { | ||
| 783 | const S = struct { | ||
| 784 | const U = union(enum) { | ||
| 785 | a: u8, | ||
| 786 | const foo = 1; | ||
| 787 | }; | ||
| 788 | |||
| 789 | fn doTheTest() !void { | ||
| 790 | try expect(!@hasDecl(Tag(U), "foo")); | ||
| 791 | } | ||
| 792 | }; | ||
| 793 | |||
| 794 | try S.doTheTest(); | ||
| 795 | } | ||
| 796 | test "anytype union field: issue #9233" { | ||
| 797 | const Baz = union(enum) { bar: anytype }; | ||
| 798 | _ = Baz; | ||
| 799 | } | ||
test/behavior/widening.zig+43| ... | @@ -17,3 +17,46 @@ test "implicit unsigned integer to signed integer" { | ... | @@ -17,3 +17,46 @@ test "implicit unsigned integer to signed integer" { |
| 17 | var b: i16 = a; | 17 | var b: i16 = a; |
| 18 | try expect(b == 250); | 18 | try expect(b == 250); |
| 19 | } | 19 | } |
| 20 | |||
| 21 | test "float widening" { | ||
| 22 | if (@import("builtin").zig_is_stage2) { | ||
| 23 | // This test is passing but it depends on compiler-rt symbols, which | ||
| 24 | // cannot yet be built with stage2 due to | ||
| 25 | // "TODO implement equality comparison between a union's tag value and an enum literal" | ||
| 26 | return error.SkipZigTest; | ||
| 27 | } | ||
| 28 | var a: f16 = 12.34; | ||
| 29 | var b: f32 = a; | ||
| 30 | var c: f64 = b; | ||
| 31 | var d: f128 = c; | ||
| 32 | try expect(a == b); | ||
| 33 | try expect(b == c); | ||
| 34 | try expect(c == d); | ||
| 35 | } | ||
| 36 | |||
| 37 | test "float widening f16 to f128" { | ||
| 38 | if (@import("builtin").zig_is_stage2) { | ||
| 39 | // This test is passing but it depends on compiler-rt symbols, which | ||
| 40 | // cannot yet be built with stage2 due to | ||
| 41 | // "TODO implement equality comparison between a union's tag value and an enum literal" | ||
| 42 | return error.SkipZigTest; | ||
| 43 | } | ||
| 44 | // TODO https://github.com/ziglang/zig/issues/3282 | ||
| 45 | if (@import("builtin").stage2_arch == .aarch64) return error.SkipZigTest; | ||
| 46 | if (@import("builtin").stage2_arch == .powerpc64le) return error.SkipZigTest; | ||
| 47 | |||
| 48 | var x: f16 = 12.34; | ||
| 49 | var y: f128 = x; | ||
| 50 | try expect(x == y); | ||
| 51 | } | ||
| 52 | |||
| 53 | test "cast small unsigned to larger signed" { | ||
| 54 | try expect(castSmallUnsignedToLargerSigned1(200) == @as(i16, 200)); | ||
| 55 | try expect(castSmallUnsignedToLargerSigned2(9999) == @as(i64, 9999)); | ||
| 56 | } | ||
| 57 | fn castSmallUnsignedToLargerSigned1(x: u8) i16 { | ||
| 58 | return x; | ||
| 59 | } | ||
| 60 | fn castSmallUnsignedToLargerSigned2(x: u16) i64 { | ||
| 61 | return x; | ||
| 62 | } |
test/behavior/widening_stage1.zig deleted-34| ... | @@ -1,34 +0,0 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const expect = std.testing.expect; | ||
| 3 | const mem = std.mem; | ||
| 4 | |||
| 5 | test "float widening" { | ||
| 6 | var a: f16 = 12.34; | ||
| 7 | var b: f32 = a; | ||
| 8 | var c: f64 = b; | ||
| 9 | var d: f128 = c; | ||
| 10 | try expect(a == b); | ||
| 11 | try expect(b == c); | ||
| 12 | try expect(c == d); | ||
| 13 | } | ||
| 14 | |||
| 15 | test "float widening f16 to f128" { | ||
| 16 | // TODO https://github.com/ziglang/zig/issues/3282 | ||
| 17 | if (@import("builtin").stage2_arch == .aarch64) return error.SkipZigTest; | ||
| 18 | if (@import("builtin").stage2_arch == .powerpc64le) return error.SkipZigTest; | ||
| 19 | |||
| 20 | var x: f16 = 12.34; | ||
| 21 | var y: f128 = x; | ||
| 22 | try expect(x == y); | ||
| 23 | } | ||
| 24 | |||
| 25 | test "cast small unsigned to larger signed" { | ||
| 26 | try expect(castSmallUnsignedToLargerSigned1(200) == @as(i16, 200)); | ||
| 27 | try expect(castSmallUnsignedToLargerSigned2(9999) == @as(i64, 9999)); | ||
| 28 | } | ||
| 29 | fn castSmallUnsignedToLargerSigned1(x: u8) i16 { | ||
| 30 | return x; | ||
| 31 | } | ||
| 32 | fn castSmallUnsignedToLargerSigned2(x: u16) i64 { | ||
| 33 | return x; | ||
| 34 | } | ||