authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-01-29 03:45:15-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-01-29 03:45:15-05:00
log225910f9341fbc725ff5e0d2c653e29bc2f21cb8
treeeac47d40ae555398c46e4ccdff9cace12eeabd3b
parent63ee6e662582ee75ac804eb1a4dbdf4457b8f2d0
parenta0a71709bc2104c708f045fbb42c6247aff136ac
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #10639 from Vexu/f80

Add f80

25 files changed, 953 insertions(+), 44 deletions(-)

CMakeLists.txt+31
...@@ -142,15 +142,19 @@ include_directories(${CLANG_INCLUDE_DIRS})...@@ -142,15 +142,19 @@ include_directories(${CLANG_INCLUDE_DIRS})
142# No patches have been applied to SoftFloat-3e142# No patches have been applied to SoftFloat-3e
143set(EMBEDDED_SOFTFLOAT_SOURCES143set(EMBEDDED_SOFTFLOAT_SOURCES
144 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/f128M_isSignalingNaN.c"144 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/f128M_isSignalingNaN.c"
145 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/extF80M_isSignalingNaN.c"
145 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_commonNaNToF128M.c"146 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_commonNaNToF128M.c"
147 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_commonNaNToExtF80M.c"
146 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_commonNaNToF16UI.c"148 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_commonNaNToF16UI.c"
147 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_commonNaNToF32UI.c"149 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_commonNaNToF32UI.c"
148 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_commonNaNToF64UI.c"150 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_commonNaNToF64UI.c"
149 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_f128MToCommonNaN.c"151 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_f128MToCommonNaN.c"
152 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_extF80MToCommonNaN.c"
150 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_f16UIToCommonNaN.c"153 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_f16UIToCommonNaN.c"
151 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_f32UIToCommonNaN.c"154 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_f32UIToCommonNaN.c"
152 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_f64UIToCommonNaN.c"155 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_f64UIToCommonNaN.c"
153 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_propagateNaNF128M.c"156 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_propagateNaNF128M.c"
157 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_propagateNaNExtF80M.c"
154 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_propagateNaNF16UI.c"158 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_propagateNaNF16UI.c"
155 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/softfloat_raiseFlags.c"159 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/softfloat_raiseFlags.c"
156 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_add.c"160 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_add.c"
...@@ -170,6 +174,7 @@ set(EMBEDDED_SOFTFLOAT_SOURCES...@@ -170,6 +174,7 @@ set(EMBEDDED_SOFTFLOAT_SOURCES
170 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_f16.c"174 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_f16.c"
171 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_f32.c"175 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_f32.c"
172 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_f64.c"176 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_f64.c"
177 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_extF80M.c"
173 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_i32.c"178 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_i32.c"
174 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_i32_r_minMag.c"179 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_i32_r_minMag.c"
175 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_i64.c"180 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_i64.c"
...@@ -178,6 +183,20 @@ set(EMBEDDED_SOFTFLOAT_SOURCES...@@ -178,6 +183,20 @@ set(EMBEDDED_SOFTFLOAT_SOURCES
178 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_ui32_r_minMag.c"183 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_ui32_r_minMag.c"
179 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_ui64.c"184 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_ui64.c"
180 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_ui64_r_minMag.c"185 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_ui64_r_minMag.c"
186 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/extF80M_add.c"
187 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/extF80M_div.c"
188 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/extF80M_eq.c"
189 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/extF80M_le.c"
190 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/extF80M_lt.c"
191 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/extF80M_mul.c"
192 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/extF80M_rem.c"
193 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/extF80M_roundToInt.c"
194 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/extF80M_sqrt.c"
195 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/extF80M_sub.c"
196 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/extF80M_to_f16.c"
197 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/extF80M_to_f32.c"
198 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/extF80M_to_f64.c"
199 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/extF80M_to_f128M.c"
181 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_add.c"200 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_add.c"
182 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_div.c"201 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_div.c"
183 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_eq.c"202 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_eq.c"
...@@ -188,9 +207,12 @@ set(EMBEDDED_SOFTFLOAT_SOURCES...@@ -188,9 +207,12 @@ set(EMBEDDED_SOFTFLOAT_SOURCES
188 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_roundToInt.c"207 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_roundToInt.c"
189 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_sqrt.c"208 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_sqrt.c"
190 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_sub.c"209 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_sub.c"
210 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_to_extF80M.c"
191 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_to_f128M.c"211 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_to_f128M.c"
192 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_to_f64.c"212 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_to_f64.c"
213 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f32_to_extF80M.c"
193 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f32_to_f128M.c"214 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f32_to_f128M.c"
215 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f64_to_extF80M.c"
194 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f64_to_f128M.c"216 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f64_to_f128M.c"
195 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f64_to_f16.c"217 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f64_to_f16.c"
196 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/i32_to_f128M.c"218 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/i32_to_f128M.c"
...@@ -198,6 +220,7 @@ set(EMBEDDED_SOFTFLOAT_SOURCES...@@ -198,6 +220,7 @@ set(EMBEDDED_SOFTFLOAT_SOURCES
198 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_addCarryM.c"220 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_addCarryM.c"
199 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_addComplCarryM.c"221 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_addComplCarryM.c"
200 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_addF128M.c"222 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_addF128M.c"
223 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_addExtF80M.c"
201 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_addM.c"224 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_addM.c"
202 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_addMagsF16.c"225 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_addMagsF16.c"
203 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_addMagsF32.c"226 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_addMagsF32.c"
...@@ -208,12 +231,14 @@ set(EMBEDDED_SOFTFLOAT_SOURCES...@@ -208,12 +231,14 @@ set(EMBEDDED_SOFTFLOAT_SOURCES
208 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_approxRecip_1Ks.c"231 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_approxRecip_1Ks.c"
209 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_compare128M.c"232 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_compare128M.c"
210 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_compare96M.c"233 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_compare96M.c"
234 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_compareNonnormExtF80M.c"
211 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_countLeadingZeros16.c"235 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_countLeadingZeros16.c"
212 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_countLeadingZeros32.c"236 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_countLeadingZeros32.c"
213 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_countLeadingZeros64.c"237 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_countLeadingZeros64.c"
214 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_countLeadingZeros8.c"238 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_countLeadingZeros8.c"
215 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_eq128.c"239 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_eq128.c"
216 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_invalidF128M.c"240 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_invalidF128M.c"
241 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_invalidExtF80M.c"
217 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_isNaNF128M.c"242 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_isNaNF128M.c"
218 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_le128.c"243 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_le128.c"
219 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_lt128.c"244 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_lt128.c"
...@@ -224,7 +249,9 @@ set(EMBEDDED_SOFTFLOAT_SOURCES...@@ -224,7 +249,9 @@ set(EMBEDDED_SOFTFLOAT_SOURCES
224 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_mulAddF32.c"249 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_mulAddF32.c"
225 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_mulAddF64.c"250 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_mulAddF64.c"
226 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_negXM.c"251 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_negXM.c"
252 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_normExtF80SigM.c"
227 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_normRoundPackMToF128M.c"253 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_normRoundPackMToF128M.c"
254 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_normRoundPackMToExtF80M.c"
228 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_normRoundPackToF16.c"255 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_normRoundPackToF16.c"
229 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_normRoundPackToF32.c"256 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_normRoundPackToF32.c"
230 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_normRoundPackToF64.c"257 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_normRoundPackToF64.c"
...@@ -235,6 +262,7 @@ set(EMBEDDED_SOFTFLOAT_SOURCES...@@ -235,6 +262,7 @@ set(EMBEDDED_SOFTFLOAT_SOURCES
235 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_remStepMBy32.c"262 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_remStepMBy32.c"
236 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_roundMToI64.c"263 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_roundMToI64.c"
237 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_roundMToUI64.c"264 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_roundMToUI64.c"
265 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_roundPackMToExtF80M.c"
238 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_roundPackMToF128M.c"266 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_roundPackMToF128M.c"
239 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_roundPackToF16.c"267 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_roundPackToF16.c"
240 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_roundPackToF32.c"268 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_roundPackToF32.c"
...@@ -263,11 +291,14 @@ set(EMBEDDED_SOFTFLOAT_SOURCES...@@ -263,11 +291,14 @@ set(EMBEDDED_SOFTFLOAT_SOURCES
263 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_subMagsF32.c"291 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_subMagsF32.c"
264 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_subMagsF64.c"292 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_subMagsF64.c"
265 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_tryPropagateNaNF128M.c"293 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_tryPropagateNaNF128M.c"
294 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_tryPropagateNaNExtF80M.c"
266 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_mulAdd.c"295 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_mulAdd.c"
267 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_mulAdd.c"296 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_mulAdd.c"
268 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/softfloat_state.c"297 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/softfloat_state.c"
269 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/ui32_to_f128M.c"298 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/ui32_to_f128M.c"
270 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/ui64_to_f128M.c"299 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/ui64_to_f128M.c"
300 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/ui32_to_extF80M.c"
301 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/ui64_to_extF80M.c"
271)302)
272add_library(embedded_softfloat STATIC ${EMBEDDED_SOFTFLOAT_SOURCES})303add_library(embedded_softfloat STATIC ${EMBEDDED_SOFTFLOAT_SOURCES})
273if(MSVC)304if(MSVC)
doc/langref.html.in+6
...@@ -737,6 +737,11 @@ pub fn main() void {...@@ -737,6 +737,11 @@ pub fn main() void {
737 <td><code class="c">double</code></td>737 <td><code class="c">double</code></td>
738 <td>64-bit floating point (52-bit mantissa) IEEE-754-2008 binary64</td>738 <td>64-bit floating point (52-bit mantissa) IEEE-754-2008 binary64</td>
739 </tr>739 </tr>
740 <tr>
741 <th scope="row">{#syntax#}f80{#endsyntax#}</th>
742 <td><code class="c">double</code></td>
743 <td>64-bit floating point (64-bit mantissa) IEEE-754-2008 80-bit extended precision</td>
744 </tr>
740 <tr>745 <tr>
741 <th scope="row">{#syntax#}f128{#endsyntax#}</th>746 <th scope="row">{#syntax#}f128{#endsyntax#}</th>
742 <td><code class="c">_Float128</code></td>747 <td><code class="c">_Float128</code></td>
...@@ -1500,6 +1505,7 @@ fn divide(a: i32, b: i32) i32 {...@@ -1500,6 +1505,7 @@ fn divide(a: i32, b: i32) i32 {
1500 <li>{#syntax#}f16{#endsyntax#} - IEEE-754-2008 binary16</li>1505 <li>{#syntax#}f16{#endsyntax#} - IEEE-754-2008 binary16</li>
1501 <li>{#syntax#}f32{#endsyntax#} - IEEE-754-2008 binary32</li>1506 <li>{#syntax#}f32{#endsyntax#} - IEEE-754-2008 binary32</li>
1502 <li>{#syntax#}f64{#endsyntax#} - IEEE-754-2008 binary64</li>1507 <li>{#syntax#}f64{#endsyntax#} - IEEE-754-2008 binary64</li>
1508 <li>{#syntax#}f80{#endsyntax#} - IEEE-754-2008 80-bit extended precision</li>
1503 <li>{#syntax#}f128{#endsyntax#} - IEEE-754-2008 binary128</li>1509 <li>{#syntax#}f128{#endsyntax#} - IEEE-754-2008 binary128</li>
1504 <li>{#syntax#}c_longdouble{#endsyntax#} - matches <code class="c">long double</code> for the target C ABI</li>1510 <li>{#syntax#}c_longdouble{#endsyntax#} - matches <code class="c">long double</code> for the target C ABI</li>
1505 </ul>1511 </ul>
lib/std/math.zig+18
...@@ -43,7 +43,21 @@ pub const f128_max = @bitCast(f128, @as(u128, 0x7FFEFFFFFFFFFFFFFFFFFFFFFFFFFFFF...@@ -43,7 +43,21 @@ pub const f128_max = @bitCast(f128, @as(u128, 0x7FFEFFFFFFFFFFFFFFFFFFFFFFFFFFFF
43pub const f128_epsilon = @bitCast(f128, @as(u128, 0x3F8F0000000000000000000000000000));43pub const f128_epsilon = @bitCast(f128, @as(u128, 0x3F8F0000000000000000000000000000));
44pub const f128_toint = 1.0 / f128_epsilon;44pub const f128_toint = 1.0 / f128_epsilon;
4545
46const F80Repr = if (@import("builtin").cpu.arch.endian() == .Little) extern struct {
47 fraction: u64,
48 exp: u16,
49} else extern struct {
50 exp: u16,
51 fraction: u64,
52};
53
46// float.h details54// float.h details
55pub const f80_true_min = @ptrCast(*const f80, &F80Repr{ .fraction = 1, .exp = 0 }).*;
56pub const f80_min = @ptrCast(*const f80, &F80Repr{ .fraction = 0x8000000000000000, .exp = 1 }).*;
57pub const f80_max = @ptrCast(*const f80, &F80Repr{ .fraction = 0xFFFFFFFFFFFFFFFF, .exp = 0x7FFE }).*;
58pub const f80_epsilon = @ptrCast(*const f80, &F80Repr{ .fraction = 0x8000000000000000, .exp = 0x3FC0 }).*;
59pub const f80_toint = 1.0 / f80_epsilon;
60
47pub const f64_true_min = 4.94065645841246544177e-324;61pub const f64_true_min = 4.94065645841246544177e-324;
48pub const f64_min = 2.2250738585072014e-308;62pub const f64_min = 2.2250738585072014e-308;
49pub const f64_max = 1.79769313486231570815e+308;63pub const f64_max = 1.79769313486231570815e+308;
...@@ -91,6 +105,10 @@ pub const qnan_f64 = @bitCast(f64, qnan_u64);...@@ -91,6 +105,10 @@ pub const qnan_f64 = @bitCast(f64, qnan_u64);
91pub const inf_u64 = @as(u64, 0x7FF << 52);105pub const inf_u64 = @as(u64, 0x7FF << 52);
92pub const inf_f64 = @bitCast(f64, inf_u64);106pub const inf_f64 = @bitCast(f64, inf_u64);
93107
108pub const inf_f80 = @ptrCast(*const f80, &F80Repr{ .fraction = 0x8000000000000000, .exp = 0x7fff }).*;
109pub const nan_f80 = @ptrCast(*const f80, &F80Repr{ .fraction = 0xA000000000000000, .exp = 0x7fff }).*;
110pub const qnan_f80 = @ptrCast(*const f80, &F80Repr{ .fraction = 0xC000000000000000, .exp = 0x7fff }).*;
111
94pub const nan_u128 = @as(u128, 0x7fff0000000000000000000000000001);112pub const nan_u128 = @as(u128, 0x7fff0000000000000000000000000001);
95pub const nan_f128 = @bitCast(f128, nan_u128);113pub const nan_f128 = @bitCast(f128, nan_u128);
96114
lib/std/math/epsilon.zig+1
...@@ -8,6 +8,7 @@ pub fn epsilon(comptime T: type) T {...@@ -8,6 +8,7 @@ pub fn epsilon(comptime T: type) T {
8 f16 => math.f16_epsilon,8 f16 => math.f16_epsilon,
9 f32 => math.f32_epsilon,9 f32 => math.f32_epsilon,
10 f64 => math.f64_epsilon,10 f64 => math.f64_epsilon,
11 f80 => math.f80_epsilon,
11 f128 => math.f128_epsilon,12 f128 => math.f128_epsilon,
12 else => @compileError("epsilon not implemented for " ++ @typeName(T)),13 else => @compileError("epsilon not implemented for " ++ @typeName(T)),
13 };14 };
lib/std/math/inf.zig+1
...@@ -7,6 +7,7 @@ pub fn inf(comptime T: type) T {...@@ -7,6 +7,7 @@ pub fn inf(comptime T: type) T {
7 f16 => math.inf_f16,7 f16 => math.inf_f16,
8 f32 => math.inf_f32,8 f32 => math.inf_f32,
9 f64 => math.inf_f64,9 f64 => math.inf_f64,
10 f80 => math.inf_f80,
10 f128 => math.inf_f128,11 f128 => math.inf_f128,
11 else => @compileError("inf not implemented for " ++ @typeName(T)),12 else => @compileError("inf not implemented for " ++ @typeName(T)),
12 };13 };
lib/std/math/nan.zig+3
...@@ -6,6 +6,7 @@ pub fn nan(comptime T: type) T {...@@ -6,6 +6,7 @@ pub fn nan(comptime T: type) T {
6 f16 => math.nan_f16,6 f16 => math.nan_f16,
7 f32 => math.nan_f32,7 f32 => math.nan_f32,
8 f64 => math.nan_f64,8 f64 => math.nan_f64,
9 f80 => math.nan_f80,
9 f128 => math.nan_f128,10 f128 => math.nan_f128,
10 else => @compileError("nan not implemented for " ++ @typeName(T)),11 else => @compileError("nan not implemented for " ++ @typeName(T)),
11 };12 };
...@@ -19,6 +20,8 @@ pub fn snan(comptime T: type) T {...@@ -19,6 +20,8 @@ pub fn snan(comptime T: type) T {
19 f16 => @bitCast(f16, math.nan_u16),20 f16 => @bitCast(f16, math.nan_u16),
20 f32 => @bitCast(f32, math.nan_u32),21 f32 => @bitCast(f32, math.nan_u32),
21 f64 => @bitCast(f64, math.nan_u64),22 f64 => @bitCast(f64, math.nan_u64),
23 f80 => @bitCast(f80, math.nan_u80),
24 f128 => @bitCast(f128, math.nan_u128),
22 else => @compileError("snan not implemented for " ++ @typeName(T)),25 else => @compileError("snan not implemented for " ++ @typeName(T)),
23 };26 };
24}27}
src/AstGen.zig+2
...@@ -7723,6 +7723,7 @@ const primitives = std.ComptimeStringMap(Zir.Inst.Ref, .{...@@ -7723,6 +7723,7 @@ const primitives = std.ComptimeStringMap(Zir.Inst.Ref, .{
7723 .{ "f16", .f16_type },7723 .{ "f16", .f16_type },
7724 .{ "f32", .f32_type },7724 .{ "f32", .f32_type },
7725 .{ "f64", .f64_type },7725 .{ "f64", .f64_type },
7726 .{ "f80", .f80_type },
7726 .{ "false", .bool_false },7727 .{ "false", .bool_false },
7727 .{ "i16", .i16_type },7728 .{ "i16", .i16_type },
7728 .{ "i32", .i32_type },7729 .{ "i32", .i32_type },
...@@ -8732,6 +8733,7 @@ fn rvalue(...@@ -8732,6 +8733,7 @@ fn rvalue(
8732 as_ty | @enumToInt(Zir.Inst.Ref.f16_type),8733 as_ty | @enumToInt(Zir.Inst.Ref.f16_type),
8733 as_ty | @enumToInt(Zir.Inst.Ref.f32_type),8734 as_ty | @enumToInt(Zir.Inst.Ref.f32_type),
8734 as_ty | @enumToInt(Zir.Inst.Ref.f64_type),8735 as_ty | @enumToInt(Zir.Inst.Ref.f64_type),
8736 as_ty | @enumToInt(Zir.Inst.Ref.f80_type),
8735 as_ty | @enumToInt(Zir.Inst.Ref.f128_type),8737 as_ty | @enumToInt(Zir.Inst.Ref.f128_type),
8736 as_ty | @enumToInt(Zir.Inst.Ref.anyopaque_type),8738 as_ty | @enumToInt(Zir.Inst.Ref.anyopaque_type),
8737 as_ty | @enumToInt(Zir.Inst.Ref.bool_type),8739 as_ty | @enumToInt(Zir.Inst.Ref.bool_type),
src/Sema.zig+3
...@@ -16950,6 +16950,7 @@ pub fn typeHasOnePossibleValue(...@@ -16950,6 +16950,7 @@ pub fn typeHasOnePossibleValue(
16950 .f16,16950 .f16,
16951 .f32,16951 .f32,
16952 .f64,16952 .f64,
16953 .f80,
16953 .f128,16954 .f128,
16954 .c_longdouble,16955 .c_longdouble,
16955 .comptime_int,16956 .comptime_int,
...@@ -17227,6 +17228,7 @@ pub fn addType(sema: *Sema, ty: Type) !Air.Inst.Ref {...@@ -17227,6 +17228,7 @@ pub fn addType(sema: *Sema, ty: Type) !Air.Inst.Ref {
17227 .f16 => return .f16_type,17228 .f16 => return .f16_type,
17228 .f32 => return .f32_type,17229 .f32 => return .f32_type,
17229 .f64 => return .f64_type,17230 .f64 => return .f64_type,
17231 .f80 => return .f80_type,
17230 .f128 => return .f128_type,17232 .f128 => return .f128_type,
17231 .anyopaque => return .anyopaque_type,17233 .anyopaque => return .anyopaque_type,
17232 .bool => return .bool_type,17234 .bool => return .bool_type,
...@@ -17572,6 +17574,7 @@ fn typeRequiresComptime(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) C...@@ -17572,6 +17574,7 @@ fn typeRequiresComptime(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) C
17572 .f16,17574 .f16,
17573 .f32,17575 .f32,
17574 .f64,17576 .f64,
17577 .f80,
17575 .f128,17578 .f128,
17576 .anyopaque,17579 .anyopaque,
17577 .bool,17580 .bool,
src/Zir.zig+5
...@@ -1639,6 +1639,7 @@ pub const Inst = struct {...@@ -1639,6 +1639,7 @@ pub const Inst = struct {
1639 f16_type,1639 f16_type,
1640 f32_type,1640 f32_type,
1641 f64_type,1641 f64_type,
1642 f80_type,
1642 f128_type,1643 f128_type,
1643 anyopaque_type,1644 anyopaque_type,
1644 bool_type,1645 bool_type,
...@@ -1809,6 +1810,10 @@ pub const Inst = struct {...@@ -1809,6 +1810,10 @@ pub const Inst = struct {
1809 .ty = Type.initTag(.type),1810 .ty = Type.initTag(.type),
1810 .val = Value.initTag(.f64_type),1811 .val = Value.initTag(.f64_type),
1811 },1812 },
1813 .f80_type = .{
1814 .ty = Type.initTag(.type),
1815 .val = Value.initTag(.f80_type),
1816 },
1812 .f128_type = .{1817 .f128_type = .{
1813 .ty = Type.initTag(.type),1818 .ty = Type.initTag(.type),
1814 .val = Value.initTag(.f128_type),1819 .val = Value.initTag(.f128_type),
src/stage1/all_types.hpp+2
...@@ -516,6 +516,7 @@ struct ZigValue {...@@ -516,6 +516,7 @@ struct ZigValue {
516 float16_t x_f16;516 float16_t x_f16;
517 float x_f32;517 float x_f32;
518 double x_f64;518 double x_f64;
519 extFloat80_t x_f80;
519 float128_t x_f128;520 float128_t x_f128;
520 bool x_bool;521 bool x_bool;
521 ConstBoundFnValue x_bound_fn;522 ConstBoundFnValue x_bound_fn;
...@@ -2089,6 +2090,7 @@ struct CodeGen {...@@ -2089,6 +2090,7 @@ struct CodeGen {
2089 ZigType *entry_f16;2090 ZigType *entry_f16;
2090 ZigType *entry_f32;2091 ZigType *entry_f32;
2091 ZigType *entry_f64;2092 ZigType *entry_f64;
2093 ZigType *entry_f80;
2092 ZigType *entry_f128;2094 ZigType *entry_f128;
2093 ZigType *entry_void;2095 ZigType *entry_void;
2094 ZigType *entry_unreachable;2096 ZigType *entry_unreachable;
src/stage1/analyze.cpp+13
...@@ -5647,6 +5647,9 @@ static uint32_t hash_combine_const_val(uint32_t hash_val, ZigValue *const_val) {...@@ -5647,6 +5647,9 @@ static uint32_t hash_combine_const_val(uint32_t hash_val, ZigValue *const_val) {
5647 case 16: return hash_combine(hash_val, &const_val->data.x_f16);5647 case 16: return hash_combine(hash_val, &const_val->data.x_f16);
5648 case 32: return hash_combine(hash_val, &const_val->data.x_f32);5648 case 32: return hash_combine(hash_val, &const_val->data.x_f32);
5649 case 64: return hash_combine(hash_val, &const_val->data.x_f64);5649 case 64: return hash_combine(hash_val, &const_val->data.x_f64);
5650 case 80:
5651 hash_val = hash_combine(hash_val, &const_val->data.x_f80.signExp);
5652 return hash_combine(hash_val, &const_val->data.x_f80.signif);
5650 case 128: return hash_combine(hash_val, &const_val->data.x_f128);5653 case 128: return hash_combine(hash_val, &const_val->data.x_f128);
5651 default: zig_unreachable();5654 default: zig_unreachable();
5652 }5655 }
...@@ -6325,6 +6328,7 @@ void init_const_float(ZigValue *const_val, ZigType *type, double value) {...@@ -6325,6 +6328,7 @@ void init_const_float(ZigValue *const_val, ZigType *type, double value) {
6325 case 64:6328 case 64:
6326 const_val->data.x_f64 = value;6329 const_val->data.x_f64 = value;
6327 break;6330 break;
6331 case 80:
6328 case 128:6332 case 128:
6329 // if we need this, we should add a function that accepts a float128_t param6333 // if we need this, we should add a function that accepts a float128_t param
6330 zig_unreachable();6334 zig_unreachable();
...@@ -7218,6 +7222,8 @@ bool const_values_equal(CodeGen *g, ZigValue *a, ZigValue *b) {...@@ -7218,6 +7222,8 @@ bool const_values_equal(CodeGen *g, ZigValue *a, ZigValue *b) {
7218 return a->data.x_f32 == b->data.x_f32;7222 return a->data.x_f32 == b->data.x_f32;
7219 case 64:7223 case 64:
7220 return a->data.x_f64 == b->data.x_f64;7224 return a->data.x_f64 == b->data.x_f64;
7225 case 80:
7226 return extF80M_eq(&a->data.x_f80, &b->data.x_f80);
7221 case 128:7227 case 128:
7222 return f128M_eq(&a->data.x_f128, &b->data.x_f128);7228 return f128M_eq(&a->data.x_f128, &b->data.x_f128);
7223 default:7229 default:
...@@ -7470,6 +7476,13 @@ void render_const_value(CodeGen *g, Buf *buf, ZigValue *const_val) {...@@ -7470,6 +7476,13 @@ void render_const_value(CodeGen *g, Buf *buf, ZigValue *const_val) {
7470 case 64:7476 case 64:
7471 buf_appendf(buf, "%f", const_val->data.x_f64);7477 buf_appendf(buf, "%f", const_val->data.x_f64);
7472 return;7478 return;
7479 case 80: {
7480 float64_t f64_value = extF80M_to_f64(&const_val->data.x_f80);
7481 double double_value;
7482 memcpy(&double_value, &f64_value, sizeof(double));
7483 buf_appendf(buf, "%f", double_value);
7484 return;
7485 }
7473 case 128:7486 case 128:
7474 {7487 {
7475 const size_t extra_len = 100;7488 const size_t extra_len = 100;
src/stage1/codegen.cpp+444-12
...@@ -1598,6 +1598,81 @@ static LLVMValueRef gen_assert_zero(CodeGen *g, LLVMValueRef expr_val, ZigType *...@@ -1598,6 +1598,81 @@ static LLVMValueRef gen_assert_zero(CodeGen *g, LLVMValueRef expr_val, ZigType *
1598 return nullptr;1598 return nullptr;
1599}1599}
16001600
1601
1602static LLVMValueRef gen_soft_f80_widen_or_shorten(CodeGen *g, ZigType *actual_type,
1603 ZigType *wanted_type, LLVMValueRef expr_val)
1604{
1605 ZigType *scalar_actual_type = (actual_type->id == ZigTypeIdVector) ?
1606 actual_type->data.vector.elem_type : actual_type;
1607 ZigType *scalar_wanted_type = (wanted_type->id == ZigTypeIdVector) ?
1608 wanted_type->data.vector.elem_type : wanted_type;
1609 uint64_t actual_bits = scalar_actual_type->data.floating.bit_count;
1610 uint64_t wanted_bits = scalar_wanted_type->data.floating.bit_count;
1611
1612
1613 LLVMTypeRef param_type;
1614 LLVMTypeRef return_type;
1615 const char *func_name;
1616
1617 if (actual_bits == wanted_bits) {
1618 return expr_val;
1619 } else if (actual_bits == 80) {
1620 param_type = g->builtin_types.entry_f80->llvm_type;
1621 switch (wanted_bits) {
1622 case 16:
1623 return_type = g->builtin_types.entry_f16->llvm_type;
1624 func_name = "__truncxfhf2";
1625 break;
1626 case 32:
1627 return_type = g->builtin_types.entry_f32->llvm_type;
1628 func_name = "__truncxfff2";
1629 break;
1630 case 64:
1631 return_type = g->builtin_types.entry_f64->llvm_type;
1632 func_name = "__truncxfdf2";
1633 break;
1634 case 128:
1635 return_type = g->builtin_types.entry_f128->llvm_type;
1636 func_name = "__extendxftf2";
1637 break;
1638 default:
1639 zig_unreachable();
1640 }
1641 } else if (wanted_bits == 80) {
1642 return_type = g->builtin_types.entry_f80->llvm_type;
1643 switch (actual_bits) {
1644 case 16:
1645 param_type = g->builtin_types.entry_f16->llvm_type;
1646 func_name = "__extendhfxf2";
1647 break;
1648 case 32:
1649 param_type = g->builtin_types.entry_f32->llvm_type;
1650 func_name = "__extendffxf2";
1651 break;
1652 case 64:
1653 param_type = g->builtin_types.entry_f64->llvm_type;
1654 func_name = "__extenddfxf2";
1655 break;
1656 case 128:
1657 param_type = g->builtin_types.entry_f128->llvm_type;
1658 func_name = "__trunctfxf2";
1659 break;
1660 default:
1661 zig_unreachable();
1662 }
1663 } else {
1664 zig_unreachable();
1665 }
1666
1667 LLVMValueRef func_ref = LLVMGetNamedFunction(g->module, func_name);
1668 if (func_ref == nullptr) {
1669 LLVMTypeRef fn_type = LLVMFunctionType(return_type, &param_type, 1, false);
1670 func_ref = LLVMAddFunction(g->module, func_name, fn_type);
1671 }
1672
1673 return LLVMBuildCall(g->builder, func_ref, &expr_val, 1, "");
1674}
1675
1601static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, ZigType *actual_type,1676static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, ZigType *actual_type,
1602 ZigType *wanted_type, LLVMValueRef expr_val)1677 ZigType *wanted_type, LLVMValueRef expr_val)
1603{1678{
...@@ -1612,6 +1687,13 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, Z...@@ -1612,6 +1687,13 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, Z
1612 uint64_t actual_bits;1687 uint64_t actual_bits;
1613 uint64_t wanted_bits;1688 uint64_t wanted_bits;
1614 if (scalar_actual_type->id == ZigTypeIdFloat) {1689 if (scalar_actual_type->id == ZigTypeIdFloat) {
1690
1691 if ((scalar_actual_type == g->builtin_types.entry_f80
1692 || scalar_wanted_type == g->builtin_types.entry_f80)
1693 && !target_has_f80(g->zig_target))
1694 {
1695 return gen_soft_f80_widen_or_shorten(g, actual_type, wanted_type, expr_val);
1696 }
1615 actual_bits = scalar_actual_type->data.floating.bit_count;1697 actual_bits = scalar_actual_type->data.floating.bit_count;
1616 wanted_bits = scalar_wanted_type->data.floating.bit_count;1698 wanted_bits = scalar_wanted_type->data.floating.bit_count;
1617 } else if (scalar_actual_type->id == ZigTypeIdInt) {1699 } else if (scalar_actual_type->id == ZigTypeIdInt) {
...@@ -3142,6 +3224,187 @@ static void gen_shift_rhs_check(CodeGen *g, ZigType *lhs_type, ZigType *rhs_type...@@ -3142,6 +3224,187 @@ static void gen_shift_rhs_check(CodeGen *g, ZigType *lhs_type, ZigType *rhs_type
3142 }3224 }
3143}3225}
31443226
3227static LLVMValueRef get_soft_f80_bin_op_func(CodeGen *g, const char *name, int param_count, LLVMTypeRef return_type) {
3228 LLVMValueRef existing_llvm_fn = LLVMGetNamedFunction(g->module, name);
3229 if (existing_llvm_fn != nullptr) return existing_llvm_fn;
3230
3231 LLVMTypeRef float_type_ref = g->builtin_types.entry_f80->llvm_type;
3232 LLVMTypeRef param_types[2] = { float_type_ref, float_type_ref };
3233 LLVMTypeRef fn_type = LLVMFunctionType(return_type, param_types, param_count, false);
3234 return LLVMAddFunction(g->module, name, fn_type);
3235}
3236
3237static LLVMValueRef ir_render_soft_f80_bin_op(CodeGen *g, Stage1Air *executable,
3238 Stage1AirInstBinOp *bin_op_instruction)
3239{
3240 IrBinOp op_id = bin_op_instruction->op_id;
3241 Stage1AirInst *op1 = bin_op_instruction->op1;
3242 Stage1AirInst *op2 = bin_op_instruction->op2;
3243 uint32_t vector_len = op1->value->type->id == ZigTypeIdVector ? op1->value->type->data.vector.len : 0;
3244
3245 LLVMValueRef op1_value = ir_llvm_value(g, op1);
3246 LLVMValueRef op2_value = ir_llvm_value(g, op2);
3247
3248 bool div_exact_safety_check = false;
3249 LLVMTypeRef return_type = g->builtin_types.entry_f80->llvm_type;
3250 int param_count = 2;
3251 const char *func_name;
3252 switch (op_id) {
3253 case IrBinOpInvalid:
3254 case IrBinOpArrayCat:
3255 case IrBinOpArrayMult:
3256 case IrBinOpRemUnspecified:
3257 case IrBinOpBitShiftLeftLossy:
3258 case IrBinOpBitShiftLeftExact:
3259 case IrBinOpBitShiftRightLossy:
3260 case IrBinOpBitShiftRightExact:
3261 case IrBinOpBoolOr:
3262 case IrBinOpBoolAnd:
3263 case IrBinOpMultWrap:
3264 case IrBinOpAddWrap:
3265 case IrBinOpSubWrap:
3266 case IrBinOpBinOr:
3267 case IrBinOpBinXor:
3268 case IrBinOpBinAnd:
3269 case IrBinOpAddSat:
3270 case IrBinOpSubSat:
3271 case IrBinOpMultSat:
3272 case IrBinOpShlSat:
3273 zig_unreachable();
3274 case IrBinOpCmpEq:
3275 return_type = g->builtin_types.entry_i32->llvm_type;
3276 func_name = "__eqxf2";
3277 break;
3278 case IrBinOpCmpNotEq:
3279 return_type = g->builtin_types.entry_i32->llvm_type;
3280 func_name = "__nexf2";
3281 break;
3282 case IrBinOpCmpLessOrEq:
3283 case IrBinOpCmpLessThan:
3284 return_type = g->builtin_types.entry_i32->llvm_type;
3285 func_name = "__lexf2";
3286 break;
3287 case IrBinOpCmpGreaterOrEq:
3288 case IrBinOpCmpGreaterThan:
3289 return_type = g->builtin_types.entry_i32->llvm_type;
3290 func_name = "__gexf2";
3291 break;
3292 case IrBinOpMaximum:
3293 func_name = "__fmaxx";
3294 break;
3295 case IrBinOpMinimum:
3296 func_name = "__fminx";
3297 break;
3298 case IrBinOpMult:
3299 func_name = "__mulxf3";
3300 break;
3301 case IrBinOpAdd:
3302 func_name = "__addxf3";
3303 break;
3304 case IrBinOpSub:
3305 func_name = "__subxf3";
3306 break;
3307 case IrBinOpDivUnspecified:
3308 func_name = "__divxf3";
3309 break;
3310 case IrBinOpDivExact:
3311 func_name = "__divxf3";
3312 div_exact_safety_check = bin_op_instruction->safety_check_on &&
3313 ir_want_runtime_safety(g, &bin_op_instruction->base);
3314 break;
3315 case IrBinOpDivTrunc:
3316 param_count = 1;
3317 func_name = "__truncx";
3318 break;
3319 case IrBinOpDivFloor:
3320 param_count = 1;
3321 func_name = "__floorx";
3322 break;
3323 case IrBinOpRemRem:
3324 param_count = 1;
3325 func_name = "__remx";
3326 break;
3327 case IrBinOpRemMod:
3328 param_count = 1;
3329 func_name = "__modx";
3330 break;
3331 default:
3332 zig_unreachable();
3333 }
3334
3335 LLVMValueRef func_ref = get_soft_f80_bin_op_func(g, func_name, param_count, return_type);
3336
3337 LLVMValueRef result;
3338 if (vector_len == 0) {
3339 LLVMValueRef params[2] = {op1_value, op2_value};
3340 result = LLVMBuildCall(g->builder, func_ref, params, param_count, "");
3341 } else {
3342 result = build_alloca(g, op1->value->type, "", 0);
3343 }
3344
3345 LLVMTypeRef usize_ref = g->builtin_types.entry_usize->llvm_type;
3346 for (uint32_t i = 0; i < vector_len; i++) {
3347 LLVMValueRef index_value = LLVMConstInt(usize_ref, i, false);
3348 LLVMValueRef params[2] = {
3349 LLVMBuildExtractElement(g->builder, op1_value, index_value, ""),
3350 LLVMBuildExtractElement(g->builder, op2_value, index_value, ""),
3351 };
3352 LLVMValueRef call_result = LLVMBuildCall(g->builder, func_ref, params, param_count, "");
3353 LLVMBuildInsertElement(g->builder, LLVMBuildLoad(g->builder, result, ""),
3354 call_result, index_value, "");
3355 }
3356
3357 if (div_exact_safety_check) {
3358 // Safety check: a / b == floor(a / b)
3359 LLVMValueRef floor_func = get_soft_f80_bin_op_func(g, "__floorx", 1, return_type);
3360 LLVMValueRef eq_func = get_soft_f80_bin_op_func(g, "__eqxf2", 2, g->builtin_types.entry_i32->llvm_type);
3361
3362 LLVMValueRef ok_bit;
3363 if (vector_len == 0) {
3364 LLVMValueRef floored = LLVMBuildCall(g->builder, floor_func, &result, 1, "");
3365
3366 LLVMValueRef params[2] = {result, floored};
3367 ok_bit = LLVMBuildCall(g->builder, eq_func, params, 2, "");
3368 } else {
3369 ZigType *bool_vec_ty = get_vector_type(g, vector_len, g->builtin_types.entry_bool);
3370 ok_bit = build_alloca(g, bool_vec_ty, "", 0);
3371 }
3372
3373 for (uint32_t i = 0; i < vector_len; i++) {
3374 LLVMValueRef index_value = LLVMConstInt(usize_ref, i, false);
3375 LLVMValueRef div_res = LLVMBuildExtractElement(g->builder,
3376 LLVMBuildLoad(g->builder, result, ""), index_value, "");
3377
3378 LLVMValueRef params[2] = {
3379 div_res,
3380 LLVMBuildCall(g->builder, floor_func, &div_res, 1, ""),
3381 };
3382 LLVMValueRef cmp_res = LLVMBuildCall(g->builder, eq_func, params, 2, "");
3383 cmp_res = LLVMBuildTrunc(g->builder, cmp_res, g->builtin_types.entry_bool->llvm_type, "");
3384 LLVMBuildInsertElement(g->builder, LLVMBuildLoad(g->builder, ok_bit, ""),
3385 cmp_res, index_value, "");
3386 }
3387
3388 if (vector_len != 0) {
3389 ok_bit = ZigLLVMBuildAndReduce(g->builder, LLVMBuildLoad(g->builder, ok_bit, ""));
3390 }
3391 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "DivExactOk");
3392 LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "DivExactFail");
3393
3394 LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block);
3395
3396 LLVMPositionBuilderAtEnd(g->builder, fail_block);
3397 gen_safety_crash(g, PanicMsgIdExactDivisionRemainder);
3398
3399 LLVMPositionBuilderAtEnd(g->builder, ok_block);
3400 }
3401
3402 if (vector_len != 0) {
3403 result = LLVMBuildLoad(g->builder, result, "");
3404 }
3405 return result;
3406}
3407
3145static LLVMValueRef ir_render_bin_op(CodeGen *g, Stage1Air *executable,3408static LLVMValueRef ir_render_bin_op(CodeGen *g, Stage1Air *executable,
3146 Stage1AirInstBinOp *bin_op_instruction)3409 Stage1AirInstBinOp *bin_op_instruction)
3147{3410{
...@@ -3151,6 +3414,10 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, Stage1Air *executable,...@@ -3151,6 +3414,10 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, Stage1Air *executable,
31513414
3152 ZigType *operand_type = op1->value->type;3415 ZigType *operand_type = op1->value->type;
3153 ZigType *scalar_type = (operand_type->id == ZigTypeIdVector) ? operand_type->data.vector.elem_type : operand_type;3416 ZigType *scalar_type = (operand_type->id == ZigTypeIdVector) ? operand_type->data.vector.elem_type : operand_type;
3417 if (scalar_type == g->builtin_types.entry_f80 && !target_has_f80(g->zig_target)) {
3418 return ir_render_soft_f80_bin_op(g, executable, bin_op_instruction);
3419 }
3420
31543421
3155 bool want_runtime_safety = bin_op_instruction->safety_check_on &&3422 bool want_runtime_safety = bin_op_instruction->safety_check_on &&
3156 ir_want_runtime_safety(g, &bin_op_instruction->base);3423 ir_want_runtime_safety(g, &bin_op_instruction->base);
...@@ -3158,7 +3425,6 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, Stage1Air *executable,...@@ -3158,7 +3425,6 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, Stage1Air *executable,
3158 LLVMValueRef op1_value = ir_llvm_value(g, op1);3425 LLVMValueRef op1_value = ir_llvm_value(g, op1);
3159 LLVMValueRef op2_value = ir_llvm_value(g, op2);3426 LLVMValueRef op2_value = ir_llvm_value(g, op2);
31603427
3161
3162 switch (op_id) {3428 switch (op_id) {
3163 case IrBinOpInvalid:3429 case IrBinOpInvalid:
3164 case IrBinOpArrayCat:3430 case IrBinOpArrayCat:
...@@ -5927,7 +6193,7 @@ static LLVMValueRef ir_render_prefetch(CodeGen *g, Stage1Air *executable, Stage1...@@ -5927,7 +6193,7 @@ static LLVMValueRef ir_render_prefetch(CodeGen *g, Stage1Air *executable, Stage1
5927 static_assert(PrefetchCacheInstruction == 0, "");6193 static_assert(PrefetchCacheInstruction == 0, "");
5928 static_assert(PrefetchCacheData == 1, "");6194 static_assert(PrefetchCacheData == 1, "");
5929 assert(instruction->cache == PrefetchCacheData || instruction->cache == PrefetchCacheInstruction);6195 assert(instruction->cache == PrefetchCacheData || instruction->cache == PrefetchCacheInstruction);
5930 6196
5931 // LLVM fails during codegen of instruction cache prefetchs for these architectures.6197 // LLVM fails during codegen of instruction cache prefetchs for these architectures.
5932 // This is an LLVM bug as the prefetch intrinsic should be a noop if not supported by the target.6198 // This is an LLVM bug as the prefetch intrinsic should be a noop if not supported by the target.
5933 // To work around this, simply don't emit llvm.prefetch in this case.6199 // To work around this, simply don't emit llvm.prefetch in this case.
...@@ -6622,13 +6888,148 @@ static LLVMValueRef ir_render_atomic_store(CodeGen *g, Stage1Air *executable,...@@ -6622,13 +6888,148 @@ static LLVMValueRef ir_render_atomic_store(CodeGen *g, Stage1Air *executable,
6622 return nullptr;6888 return nullptr;
6623}6889}
66246890
6891static LLVMValueRef ir_render_soft_f80_float_op(CodeGen *g, Stage1Air *executable, Stage1AirInstFloatOp *instruction) {
6892 ZigType *op_type = instruction->operand->value->type;
6893 uint32_t vector_len = op_type->id == ZigTypeIdVector ? op_type->data.vector.len : 0;
6894
6895 const char *func_name;
6896 switch (instruction->fn_id) {
6897 case BuiltinFnIdSqrt:
6898 func_name = "__sqrt";
6899 break;
6900 case BuiltinFnIdSin:
6901 func_name = "__sinx";
6902 break;
6903 case BuiltinFnIdCos:
6904 func_name = "__cosx";
6905 break;
6906 case BuiltinFnIdExp:
6907 func_name = "__expx";
6908 break;
6909 case BuiltinFnIdExp2:
6910 func_name = "__exp2x";
6911 break;
6912 case BuiltinFnIdLog:
6913 func_name = "__logx";
6914 break;
6915 case BuiltinFnIdLog2:
6916 func_name = "__log2x";
6917 break;
6918 case BuiltinFnIdLog10:
6919 func_name = "__log10x";
6920 break;
6921 case BuiltinFnIdFabs:
6922 func_name = "__fabsx";
6923 break;
6924 case BuiltinFnIdFloor:
6925 func_name = "__floorx";
6926 break;
6927 case BuiltinFnIdCeil:
6928 func_name = "__ceilx";
6929 break;
6930 case BuiltinFnIdTrunc:
6931 func_name = "__truncx";
6932 break;
6933 case BuiltinFnIdNearbyInt:
6934 func_name = "__nearbyintx";
6935 break;
6936 case BuiltinFnIdRound:
6937 func_name = "__roundx";
6938 break;
6939 default:
6940 zig_unreachable();
6941 }
6942
6943
6944 LLVMValueRef func_ref = LLVMGetNamedFunction(g->module, func_name);
6945 if (func_ref == nullptr) {
6946 LLVMTypeRef f80_ref = g->builtin_types.entry_f80->llvm_type;
6947 LLVMTypeRef fn_type = LLVMFunctionType(f80_ref, &f80_ref, 1, false);
6948 func_ref = LLVMAddFunction(g->module, func_name, fn_type);
6949 }
6950
6951 LLVMValueRef operand = ir_llvm_value(g, instruction->operand);
6952 LLVMValueRef result;
6953 if (vector_len == 0) {
6954 result = LLVMBuildCall(g->builder, func_ref, &operand, 1, "");
6955 } else {
6956 result = build_alloca(g, instruction->operand->value->type, "", 0);
6957 }
6958
6959 LLVMTypeRef usize_ref = g->builtin_types.entry_usize->llvm_type;
6960 for (uint32_t i = 0; i < vector_len; i++) {
6961 LLVMValueRef index_value = LLVMConstInt(usize_ref, i, false);
6962 LLVMValueRef param = LLVMBuildExtractElement(g->builder, operand, index_value, "");
6963 LLVMValueRef call_result = LLVMBuildCall(g->builder, func_ref, &param, 1, "");
6964 LLVMBuildInsertElement(g->builder, LLVMBuildLoad(g->builder, result, ""),
6965 call_result, index_value, "");
6966 }
6967 if (vector_len != 0) {
6968 result = LLVMBuildLoad(g->builder, result, "");
6969 }
6970 return result;
6971}
6972
6625static LLVMValueRef ir_render_float_op(CodeGen *g, Stage1Air *executable, Stage1AirInstFloatOp *instruction) {6973static LLVMValueRef ir_render_float_op(CodeGen *g, Stage1Air *executable, Stage1AirInstFloatOp *instruction) {
6974 ZigType *op_type = instruction->operand->value->type;
6975 op_type = op_type->id == ZigTypeIdVector ? op_type->data.vector.elem_type : op_type;
6976 if (op_type == g->builtin_types.entry_f80 && !target_has_f80(g->zig_target)) {
6977 return ir_render_soft_f80_float_op(g, executable, instruction);
6978 }
6626 LLVMValueRef operand = ir_llvm_value(g, instruction->operand);6979 LLVMValueRef operand = ir_llvm_value(g, instruction->operand);
6627 LLVMValueRef fn_val = get_float_fn(g, instruction->base.value->type, ZigLLVMFnIdFloatOp, instruction->fn_id);6980 LLVMValueRef fn_val = get_float_fn(g, instruction->base.value->type, ZigLLVMFnIdFloatOp, instruction->fn_id);
6628 return LLVMBuildCall(g->builder, fn_val, &operand, 1, "");6981 return LLVMBuildCall(g->builder, fn_val, &operand, 1, "");
6629}6982}
66306983
6984static LLVMValueRef ir_render_soft_f80_mul_add(CodeGen *g, Stage1Air *executable, Stage1AirInstMulAdd *instruction) {
6985 ZigType *op_type = instruction->op1->value->type;
6986 uint32_t vector_len = op_type->id == ZigTypeIdVector ? op_type->data.vector.len : 0;
6987
6988 const char *func_name = "__fmax";
6989 LLVMValueRef func_ref = LLVMGetNamedFunction(g->module, func_name);
6990 if (func_ref == nullptr) {
6991 LLVMTypeRef f80_ref = g->builtin_types.entry_f80->llvm_type;
6992 LLVMTypeRef params[3] = { f80_ref, f80_ref, f80_ref };
6993 LLVMTypeRef fn_type = LLVMFunctionType(f80_ref, params, 3, false);
6994 func_ref = LLVMAddFunction(g->module, func_name, fn_type);
6995 }
6996
6997 LLVMValueRef op1 = ir_llvm_value(g, instruction->op1);
6998 LLVMValueRef op2 = ir_llvm_value(g, instruction->op2);
6999 LLVMValueRef op3 = ir_llvm_value(g, instruction->op3);
7000 LLVMValueRef result;
7001 if (vector_len == 0) {
7002 LLVMValueRef params[3] = { op1, op2, op3 };
7003 result = LLVMBuildCall(g->builder, func_ref, params, 3, "");
7004 } else {
7005 result = build_alloca(g, instruction->op1->value->type, "", 0);
7006 }
7007
7008 LLVMTypeRef usize_ref = g->builtin_types.entry_usize->llvm_type;
7009 for (uint32_t i = 0; i < vector_len; i++) {
7010 LLVMValueRef index_value = LLVMConstInt(usize_ref, i, false);
7011
7012 LLVMValueRef params[3] = {
7013 LLVMBuildExtractElement(g->builder, op1, index_value, ""),
7014 LLVMBuildExtractElement(g->builder, op2, index_value, ""),
7015 LLVMBuildExtractElement(g->builder, op3, index_value, ""),
7016 };
7017 LLVMValueRef call_result = LLVMBuildCall(g->builder, func_ref, params, 3, "");
7018 LLVMBuildInsertElement(g->builder, LLVMBuildLoad(g->builder, result, ""),
7019 call_result, index_value, "");
7020 }
7021 if (vector_len != 0) {
7022 result = LLVMBuildLoad(g->builder, result, "");
7023 }
7024 return result;
7025}
7026
6631static LLVMValueRef ir_render_mul_add(CodeGen *g, Stage1Air *executable, Stage1AirInstMulAdd *instruction) {7027static LLVMValueRef ir_render_mul_add(CodeGen *g, Stage1Air *executable, Stage1AirInstMulAdd *instruction) {
7028 ZigType *op_type = instruction->op1->value->type;
7029 op_type = op_type->id == ZigTypeIdVector ? op_type->data.vector.elem_type : op_type;
7030 if (op_type == g->builtin_types.entry_f80 && !target_has_f80(g->zig_target)) {
7031 return ir_render_soft_f80_mul_add(g, executable, instruction);
7032 }
6632 LLVMValueRef op1 = ir_llvm_value(g, instruction->op1);7033 LLVMValueRef op1 = ir_llvm_value(g, instruction->op1);
6633 LLVMValueRef op2 = ir_llvm_value(g, instruction->op2);7034 LLVMValueRef op2 = ir_llvm_value(g, instruction->op2);
6634 LLVMValueRef op3 = ir_llvm_value(g, instruction->op3);7035 LLVMValueRef op3 = ir_llvm_value(g, instruction->op3);
...@@ -7692,20 +8093,33 @@ static LLVMValueRef gen_const_val(CodeGen *g, ZigValue *const_val, const char *n...@@ -7692,20 +8093,33 @@ static LLVMValueRef gen_const_val(CodeGen *g, ZigValue *const_val, const char *n
7692 return LLVMConstReal(get_llvm_type(g, type_entry), const_val->data.x_f32);8093 return LLVMConstReal(get_llvm_type(g, type_entry), const_val->data.x_f32);
7693 case 64:8094 case 64:
7694 return LLVMConstReal(get_llvm_type(g, type_entry), const_val->data.x_f64);8095 return LLVMConstReal(get_llvm_type(g, type_entry), const_val->data.x_f64);
8096 case 80: {
8097 uint64_t buf[2];
8098 memcpy(&buf, &const_val->data.x_f80, 16);
8099#if ZIG_BYTE_ORDER == ZIG_BIG_ENDIAN
8100 uint64_t tmp = buf[0];
8101 buf[0] = buf[1];
8102 buf[1] = tmp;
8103#endif
8104 LLVMValueRef as_i128 = LLVMConstIntOfArbitraryPrecision(LLVMInt128Type(), 2, buf);
8105 LLVMValueRef as_int = LLVMConstTrunc(as_i128, LLVMIntType(80));
8106 return LLVMConstBitCast(as_int, get_llvm_type(g, type_entry));
8107 }
7695 case 128:8108 case 128:
7696 {8109 {
7697 uint64_t buf[2];8110 uint64_t buf[2];
76988111
7699 // LLVM seems to require that the lower half of the f128 be placed first in the buffer.8112 // LLVM seems to require that the lower half of the f128 be
7700 #if defined(ZIG_BYTE_ORDER) && ZIG_BYTE_ORDER == ZIG_LITTLE_ENDIAN8113 // placed first in the buffer.
7701 buf[0] = const_val->data.x_f128.v[0];8114#if ZIG_BYTE_ORDER == ZIG_LITTLE_ENDIAN
7702 buf[1] = const_val->data.x_f128.v[1];8115 buf[0] = const_val->data.x_f128.v[0];
7703 #elif defined(ZIG_BYTE_ORDER) && ZIG_BYTE_ORDER == ZIG_BIG_ENDIAN8116 buf[1] = const_val->data.x_f128.v[1];
7704 buf[0] = const_val->data.x_f128.v[1];8117#elif ZIG_BYTE_ORDER == ZIG_BIG_ENDIAN
7705 buf[1] = const_val->data.x_f128.v[0];8118 buf[0] = const_val->data.x_f128.v[1];
7706 #else8119 buf[1] = const_val->data.x_f128.v[0];
7707 #error Unsupported endian8120#else
7708 #endif8121#error Unsupported endian
8122#endif
77098123
7710 LLVMValueRef as_int = LLVMConstIntOfArbitraryPrecision(LLVMInt128Type(), 2, buf);8124 LLVMValueRef as_int = LLVMConstIntOfArbitraryPrecision(LLVMInt128Type(), 2, buf);
7711 return LLVMConstBitCast(as_int, get_llvm_type(g, type_entry));8125 return LLVMConstBitCast(as_int, get_llvm_type(g, type_entry));
...@@ -8911,6 +9325,24 @@ static void define_builtin_types(CodeGen *g) {...@@ -8911,6 +9325,24 @@ static void define_builtin_types(CodeGen *g) {
8911 add_fp_entry(g, "f64", 64, LLVMDoubleType(), &g->builtin_types.entry_f64);9325 add_fp_entry(g, "f64", 64, LLVMDoubleType(), &g->builtin_types.entry_f64);
8912 add_fp_entry(g, "f128", 128, LLVMFP128Type(), &g->builtin_types.entry_f128);9326 add_fp_entry(g, "f128", 128, LLVMFP128Type(), &g->builtin_types.entry_f128);
89139327
9328 if (target_has_f80(g->zig_target)) {
9329 add_fp_entry(g, "f80", 80, LLVMX86FP80Type(), &g->builtin_types.entry_f80);
9330 } else {
9331 ZigType *entry = new_type_table_entry(ZigTypeIdFloat);
9332 entry->llvm_type = get_int_type(g, false, 128)->llvm_type;
9333 entry->size_in_bits = 8 * LLVMStoreSizeOfType(g->target_data_ref, entry->llvm_type);
9334 entry->abi_size = LLVMABISizeOfType(g->target_data_ref, entry->llvm_type);
9335 entry->abi_align = 16;
9336 buf_init_from_str(&entry->name, "f80");
9337 entry->data.floating.bit_count = 80;
9338
9339 entry->llvm_di_type = ZigLLVMCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name),
9340 entry->size_in_bits, ZigLLVMEncoding_DW_ATE_unsigned());
9341
9342 g->builtin_types.entry_f80 = entry;
9343 g->primitive_type_table.put(&entry->name, entry);
9344 }
9345
8914 switch (g->zig_target->arch) {9346 switch (g->zig_target->arch) {
8915 case ZigLLVM_x86:9347 case ZigLLVM_x86:
8916 case ZigLLVM_x86_64:9348 case ZigLLVM_x86_64:
src/stage1/ir.cpp+239-23
...@@ -2688,6 +2688,12 @@ static bool float_has_fraction(ZigValue *const_val) {...@@ -2688,6 +2688,12 @@ static bool float_has_fraction(ZigValue *const_val) {
2688 return floorf(const_val->data.x_f32) != const_val->data.x_f32;2688 return floorf(const_val->data.x_f32) != const_val->data.x_f32;
2689 case 64:2689 case 64:
2690 return floor(const_val->data.x_f64) != const_val->data.x_f64;2690 return floor(const_val->data.x_f64) != const_val->data.x_f64;
2691 case 80:
2692 {
2693 extFloat80_t floored;
2694 extF80M_roundToInt(&const_val->data.x_f80, softfloat_round_minMag, false, &floored);
2695 return !extF80M_eq(&floored, &const_val->data.x_f80);
2696 }
2691 case 128:2697 case 128:
2692 {2698 {
2693 float128_t floored;2699 float128_t floored;
...@@ -2716,6 +2722,15 @@ static void float_append_buf(Buf *buf, ZigValue *const_val) {...@@ -2716,6 +2722,15 @@ static void float_append_buf(Buf *buf, ZigValue *const_val) {
2716 case 64:2722 case 64:
2717 buf_appendf(buf, "%f", const_val->data.x_f64);2723 buf_appendf(buf, "%f", const_val->data.x_f64);
2718 break;2724 break;
2725 case 80:
2726 {
2727 float64_t f64_value = extF80M_to_f64(&const_val->data.x_f80);
2728 double double_value;
2729 memcpy(&double_value, &f64_value, sizeof(double));
2730
2731 buf_appendf(buf, "%f", const_val->data.x_f64);
2732 break;
2733 }
2719 case 128:2734 case 128:
2720 {2735 {
2721 // TODO actual implementation2736 // TODO actual implementation
...@@ -2772,6 +2787,15 @@ static void float_init_bigint(BigInt *bigint, ZigValue *const_val) {...@@ -2772,6 +2787,15 @@ static void float_init_bigint(BigInt *bigint, ZigValue *const_val) {
2772 bigint->is_negative = true;2787 bigint->is_negative = true;
2773 }2788 }
2774 break;2789 break;
2790 case 80:
2791 {
2792 float128_t f128_value;
2793 extF80M_to_f128M(&const_val->data.x_f80, &f128_value);
2794 BigFloat tmp_float;
2795 bigfloat_init_128(&tmp_float, f128_value);
2796 bigint_init_bigfloat(bigint, &tmp_float);
2797 }
2798 break;
2775 case 128:2799 case 128:
2776 {2800 {
2777 BigFloat tmp_float;2801 BigFloat tmp_float;
...@@ -2801,8 +2825,11 @@ static void float_init_bigfloat(ZigValue *dest_val, BigFloat *bigfloat) {...@@ -2801,8 +2825,11 @@ static void float_init_bigfloat(ZigValue *dest_val, BigFloat *bigfloat) {
2801 case 64:2825 case 64:
2802 dest_val->data.x_f64 = bigfloat_to_f64(bigfloat);2826 dest_val->data.x_f64 = bigfloat_to_f64(bigfloat);
2803 break;2827 break;
2804 case 80:2828 case 80: {
2805 zig_panic("TODO: float_init_bigfloat c_longdouble");2829 float128_t f128_value = bigfloat_to_f128(bigfloat);
2830 f128M_to_extF80M(&f128_value, &dest_val->data.x_f80);
2831 break;
2832 }
2806 case 128:2833 case 128:
2807 dest_val->data.x_f128 = bigfloat_to_f128(bigfloat);2834 dest_val->data.x_f128 = bigfloat_to_f128(bigfloat);
2808 break;2835 break;
...@@ -2828,6 +2855,9 @@ static void float_init_f16(ZigValue *dest_val, float16_t x) {...@@ -2828,6 +2855,9 @@ static void float_init_f16(ZigValue *dest_val, float16_t x) {
2828 case 64:2855 case 64:
2829 dest_val->data.x_f64 = zig_f16_to_double(x);2856 dest_val->data.x_f64 = zig_f16_to_double(x);
2830 break;2857 break;
2858 case 80:
2859 f16_to_extF80M(x, &dest_val->data.x_f80);
2860 break;
2831 case 128:2861 case 128:
2832 f16_to_f128M(x, &dest_val->data.x_f128);2862 f16_to_f128M(x, &dest_val->data.x_f128);
2833 break;2863 break;
...@@ -2853,6 +2883,12 @@ static void float_init_f32(ZigValue *dest_val, float x) {...@@ -2853,6 +2883,12 @@ static void float_init_f32(ZigValue *dest_val, float x) {
2853 case 64:2883 case 64:
2854 dest_val->data.x_f64 = x;2884 dest_val->data.x_f64 = x;
2855 break;2885 break;
2886 case 80: {
2887 float32_t x_f32;
2888 memcpy(&x_f32, &x, sizeof(float));
2889 f32_to_extF80M(x_f32, &dest_val->data.x_f80);
2890 break;
2891 }
2856 case 128:2892 case 128:
2857 {2893 {
2858 float32_t x_f32;2894 float32_t x_f32;
...@@ -2882,6 +2918,12 @@ static void float_init_f64(ZigValue *dest_val, double x) {...@@ -2882,6 +2918,12 @@ static void float_init_f64(ZigValue *dest_val, double x) {
2882 case 64:2918 case 64:
2883 dest_val->data.x_f64 = x;2919 dest_val->data.x_f64 = x;
2884 break;2920 break;
2921 case 80: {
2922 float64_t x_f64;
2923 memcpy(&x_f64, &x, sizeof(double));
2924 f64_to_extF80M(x_f64, &dest_val->data.x_f80);
2925 break;
2926 }
2885 case 128:2927 case 128:
2886 {2928 {
2887 float64_t x_f64;2929 float64_t x_f64;
...@@ -2917,6 +2959,9 @@ static void float_init_f128(ZigValue *dest_val, float128_t x) {...@@ -2917,6 +2959,9 @@ static void float_init_f128(ZigValue *dest_val, float128_t x) {
2917 memcpy(&dest_val->data.x_f64, &f64_val, sizeof(double));2959 memcpy(&dest_val->data.x_f64, &f64_val, sizeof(double));
2918 break;2960 break;
2919 }2961 }
2962 case 80:
2963 f128M_to_extF80M(&x, &dest_val->data.x_f80);
2964 break;
2920 case 128:2965 case 128:
2921 {2966 {
2922 memcpy(&dest_val->data.x_f128, &x, sizeof(float128_t));2967 memcpy(&dest_val->data.x_f128, &x, sizeof(float128_t));
...@@ -2944,6 +2989,12 @@ static void float_init_float(ZigValue *dest_val, ZigValue *src_val) {...@@ -2944,6 +2989,12 @@ static void float_init_float(ZigValue *dest_val, ZigValue *src_val) {
2944 case 64:2989 case 64:
2945 float_init_f64(dest_val, src_val->data.x_f64);2990 float_init_f64(dest_val, src_val->data.x_f64);
2946 break;2991 break;
2992 case 80: {
2993 float128_t f128_value;
2994 extF80M_to_f128M(&src_val->data.x_f80, &f128_value);
2995 float_init_f128(dest_val, f128_value);
2996 break;
2997 }
2947 case 128:2998 case 128:
2948 float_init_f128(dest_val, src_val->data.x_f128);2999 float_init_f128(dest_val, src_val->data.x_f128);
2949 break;3000 break;
...@@ -2966,6 +3017,8 @@ static bool float_is_nan(ZigValue *op) {...@@ -2966,6 +3017,8 @@ static bool float_is_nan(ZigValue *op) {
2966 return op->data.x_f32 != op->data.x_f32;3017 return op->data.x_f32 != op->data.x_f32;
2967 case 64:3018 case 64:
2968 return op->data.x_f64 != op->data.x_f64;3019 return op->data.x_f64 != op->data.x_f64;
3020 case 80:
3021 return zig_extF80_isNaN(&op->data.x_f80);
2969 case 128:3022 case 128:
2970 return zig_f128_isNaN(&op->data.x_f128);3023 return zig_f128_isNaN(&op->data.x_f128);
2971 default:3024 default:
...@@ -3006,6 +3059,14 @@ static Cmp float_cmp(ZigValue *op1, ZigValue *op2) {...@@ -3006,6 +3059,14 @@ static Cmp float_cmp(ZigValue *op1, ZigValue *op2) {
3006 } else {3059 } else {
3007 return CmpEQ;3060 return CmpEQ;
3008 }3061 }
3062 case 80:
3063 if (extF80M_lt(&op1->data.x_f80, &op2->data.x_f80)) {
3064 return CmpLT;
3065 } else if (extF80M_eq(&op1->data.x_f80, &op2->data.x_f80)) {
3066 return CmpEQ;
3067 } else {
3068 return CmpGT;
3069 }
3009 case 128:3070 case 128:
3010 if (f128M_lt(&op1->data.x_f128, &op2->data.x_f128)) {3071 if (f128M_lt(&op1->data.x_f128, &op2->data.x_f128)) {
3011 return CmpLT;3072 return CmpLT;
...@@ -3061,7 +3122,18 @@ static Cmp float_cmp_zero(ZigValue *op) {...@@ -3061,7 +3122,18 @@ static Cmp float_cmp_zero(ZigValue *op) {
3061 } else {3122 } else {
3062 return CmpEQ;3123 return CmpEQ;
3063 }3124 }
3064 case 128:3125 case 80: {
3126 extFloat80_t zero_float;
3127 ui32_to_extF80M(0, &zero_float);
3128 if (extF80M_lt(&op->data.x_f80, &zero_float)) {
3129 return CmpLT;
3130 } else if (extF80M_eq(&op->data.x_f80, &zero_float)) {
3131 return CmpEQ;
3132 } else {
3133 return CmpGT;
3134 }
3135 }
3136 case 128: {
3065 float128_t zero_float;3137 float128_t zero_float;
3066 ui32_to_f128M(0, &zero_float);3138 ui32_to_f128M(0, &zero_float);
3067 if (f128M_lt(&op->data.x_f128, &zero_float)) {3139 if (f128M_lt(&op->data.x_f128, &zero_float)) {
...@@ -3071,6 +3143,7 @@ static Cmp float_cmp_zero(ZigValue *op) {...@@ -3071,6 +3143,7 @@ static Cmp float_cmp_zero(ZigValue *op) {
3071 } else {3143 } else {
3072 return CmpGT;3144 return CmpGT;
3073 }3145 }
3146 }
3074 default:3147 default:
3075 zig_unreachable();3148 zig_unreachable();
3076 }3149 }
...@@ -3095,6 +3168,9 @@ static void float_add(ZigValue *out_val, ZigValue *op1, ZigValue *op2) {...@@ -3095,6 +3168,9 @@ static void float_add(ZigValue *out_val, ZigValue *op1, ZigValue *op2) {
3095 case 64:3168 case 64:
3096 out_val->data.x_f64 = op1->data.x_f64 + op2->data.x_f64;3169 out_val->data.x_f64 = op1->data.x_f64 + op2->data.x_f64;
3097 return;3170 return;
3171 case 80:
3172 extF80M_add(&op1->data.x_f80, &op2->data.x_f80, &out_val->data.x_f80);
3173 return;
3098 case 128:3174 case 128:
3099 f128M_add(&op1->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128);3175 f128M_add(&op1->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128);
3100 return;3176 return;
...@@ -3122,6 +3198,9 @@ static void float_sub(ZigValue *out_val, ZigValue *op1, ZigValue *op2) {...@@ -3122,6 +3198,9 @@ static void float_sub(ZigValue *out_val, ZigValue *op1, ZigValue *op2) {
3122 case 64:3198 case 64:
3123 out_val->data.x_f64 = op1->data.x_f64 - op2->data.x_f64;3199 out_val->data.x_f64 = op1->data.x_f64 - op2->data.x_f64;
3124 return;3200 return;
3201 case 80:
3202 extF80M_sub(&op1->data.x_f80, &op2->data.x_f80, &out_val->data.x_f80);
3203 return;
3125 case 128:3204 case 128:
3126 f128M_sub(&op1->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128);3205 f128M_sub(&op1->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128);
3127 return;3206 return;
...@@ -3149,6 +3228,9 @@ static void float_mul(ZigValue *out_val, ZigValue *op1, ZigValue *op2) {...@@ -3149,6 +3228,9 @@ static void float_mul(ZigValue *out_val, ZigValue *op1, ZigValue *op2) {
3149 case 64:3228 case 64:
3150 out_val->data.x_f64 = op1->data.x_f64 * op2->data.x_f64;3229 out_val->data.x_f64 = op1->data.x_f64 * op2->data.x_f64;
3151 return;3230 return;
3231 case 80:
3232 extF80M_mul(&op1->data.x_f80, &op2->data.x_f80, &out_val->data.x_f80);
3233 return;
3152 case 128:3234 case 128:
3153 f128M_mul(&op1->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128);3235 f128M_mul(&op1->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128);
3154 return;3236 return;
...@@ -3176,6 +3258,9 @@ static void float_div(ZigValue *out_val, ZigValue *op1, ZigValue *op2) {...@@ -3176,6 +3258,9 @@ static void float_div(ZigValue *out_val, ZigValue *op1, ZigValue *op2) {
3176 case 64:3258 case 64:
3177 out_val->data.x_f64 = op1->data.x_f64 / op2->data.x_f64;3259 out_val->data.x_f64 = op1->data.x_f64 / op2->data.x_f64;
3178 return;3260 return;
3261 case 80:
3262 extF80M_div(&op1->data.x_f80, &op2->data.x_f80, &out_val->data.x_f80);
3263 return;
3179 case 128:3264 case 128:
3180 f128M_div(&op1->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128);3265 f128M_div(&op1->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128);
3181 return;3266 return;
...@@ -3204,6 +3289,10 @@ static void float_div_trunc(ZigValue *out_val, ZigValue *op1, ZigValue *op2) {...@@ -3204,6 +3289,10 @@ static void float_div_trunc(ZigValue *out_val, ZigValue *op1, ZigValue *op2) {
3204 case 64:3289 case 64:
3205 out_val->data.x_f64 = trunc(op1->data.x_f64 / op2->data.x_f64);3290 out_val->data.x_f64 = trunc(op1->data.x_f64 / op2->data.x_f64);
3206 return;3291 return;
3292 case 80:
3293 extF80M_div(&op1->data.x_f80, &op2->data.x_f80, &out_val->data.x_f80);
3294 extF80M_roundToInt(&out_val->data.x_f80, softfloat_round_minMag, false, &out_val->data.x_f80);
3295 return;
3207 case 128:3296 case 128:
3208 f128M_div(&op1->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128);3297 f128M_div(&op1->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128);
3209 f128M_roundToInt(&out_val->data.x_f128, softfloat_round_minMag, false, &out_val->data.x_f128);3298 f128M_roundToInt(&out_val->data.x_f128, softfloat_round_minMag, false, &out_val->data.x_f128);
...@@ -3233,6 +3322,10 @@ static void float_div_floor(ZigValue *out_val, ZigValue *op1, ZigValue *op2) {...@@ -3233,6 +3322,10 @@ static void float_div_floor(ZigValue *out_val, ZigValue *op1, ZigValue *op2) {
3233 case 64:3322 case 64:
3234 out_val->data.x_f64 = floor(op1->data.x_f64 / op2->data.x_f64);3323 out_val->data.x_f64 = floor(op1->data.x_f64 / op2->data.x_f64);
3235 return;3324 return;
3325 case 80:
3326 extF80M_div(&op1->data.x_f80, &op2->data.x_f80, &out_val->data.x_f80);
3327 extF80M_roundToInt(&out_val->data.x_f80, softfloat_round_min, false, &out_val->data.x_f80);
3328 return;
3236 case 128:3329 case 128:
3237 f128M_div(&op1->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128);3330 f128M_div(&op1->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128);
3238 f128M_roundToInt(&out_val->data.x_f128, softfloat_round_min, false, &out_val->data.x_f128);3331 f128M_roundToInt(&out_val->data.x_f128, softfloat_round_min, false, &out_val->data.x_f128);
...@@ -3261,6 +3354,9 @@ static void float_rem(ZigValue *out_val, ZigValue *op1, ZigValue *op2) {...@@ -3261,6 +3354,9 @@ static void float_rem(ZigValue *out_val, ZigValue *op1, ZigValue *op2) {
3261 case 64:3354 case 64:
3262 out_val->data.x_f64 = fmod(op1->data.x_f64, op2->data.x_f64);3355 out_val->data.x_f64 = fmod(op1->data.x_f64, op2->data.x_f64);
3263 return;3356 return;
3357 case 80:
3358 extF80M_rem(&op1->data.x_f80, &op2->data.x_f80, &out_val->data.x_f80);
3359 return;
3264 case 128:3360 case 128:
3265 f128M_rem(&op1->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128);3361 f128M_rem(&op1->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128);
3266 return;3362 return;
...@@ -3290,6 +3386,14 @@ static void zig_f128M_mod(const float128_t* a, const float128_t* b, float128_t*...@@ -3290,6 +3386,14 @@ static void zig_f128M_mod(const float128_t* a, const float128_t* b, float128_t*
3290 f128M_sub(a, c, c);3386 f128M_sub(a, c, c);
3291}3387}
32923388
3389// c = a - b * trunc(a / b)
3390static void zig_extF80M_mod(const extFloat80_t* a, const extFloat80_t* b, extFloat80_t* c) {
3391 extF80M_div(a, b, c);
3392 extF80M_roundToInt(c, softfloat_round_min, true, c);
3393 extF80M_mul(b, c, c);
3394 extF80M_sub(a, c, c);
3395}
3396
3293static void float_mod(ZigValue *out_val, ZigValue *op1, ZigValue *op2) {3397static void float_mod(ZigValue *out_val, ZigValue *op1, ZigValue *op2) {
3294 assert(op1->type == op2->type);3398 assert(op1->type == op2->type);
3295 out_val->type = op1->type;3399 out_val->type = op1->type;
...@@ -3306,6 +3410,9 @@ static void float_mod(ZigValue *out_val, ZigValue *op1, ZigValue *op2) {...@@ -3306,6 +3410,9 @@ static void float_mod(ZigValue *out_val, ZigValue *op1, ZigValue *op2) {
3306 case 64:3410 case 64:
3307 out_val->data.x_f64 = fmod(fmod(op1->data.x_f64, op2->data.x_f64) + op2->data.x_f64, op2->data.x_f64);3411 out_val->data.x_f64 = fmod(fmod(op1->data.x_f64, op2->data.x_f64) + op2->data.x_f64, op2->data.x_f64);
3308 return;3412 return;
3413 case 80:
3414 zig_extF80M_mod(&op1->data.x_f80, &op2->data.x_f80, &out_val->data.x_f80);
3415 return;
3309 case 128:3416 case 128:
3310 zig_f128M_mod(&op1->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128);3417 zig_f128M_mod(&op1->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128);
3311 return;3418 return;
...@@ -3351,6 +3458,15 @@ static void float_max(ZigValue *out_val, ZigValue *op1, ZigValue *op2) {...@@ -3351,6 +3458,15 @@ static void float_max(ZigValue *out_val, ZigValue *op1, ZigValue *op2) {
3351 out_val->data.x_f64 = op1->data.x_f64 > op2->data.x_f64 ? op1->data.x_f64 : op2->data.x_f64;3458 out_val->data.x_f64 = op1->data.x_f64 > op2->data.x_f64 ? op1->data.x_f64 : op2->data.x_f64;
3352 }3459 }
3353 return;3460 return;
3461 case 80:
3462 if (zig_extF80_isNaN(&op1->data.x_f80)) {
3463 out_val->data.x_f80 = op2->data.x_f80;
3464 } else if (zig_extF80_isNaN(&op2->data.x_f80)) {
3465 out_val->data.x_f80 = op1->data.x_f80;
3466 } else {
3467 out_val->data.x_f80 = extF80M_lt(&op1->data.x_f80, &op2->data.x_f80) ? op2->data.x_f80 : op1->data.x_f80;
3468 }
3469 return;
3354 case 128:3470 case 128:
3355 if (zig_f128_isNaN(&op1->data.x_f128)) {3471 if (zig_f128_isNaN(&op1->data.x_f128)) {
3356 out_val->data.x_f128 = op2->data.x_f128;3472 out_val->data.x_f128 = op2->data.x_f128;
...@@ -3402,6 +3518,15 @@ static void float_min(ZigValue *out_val, ZigValue *op1, ZigValue *op2) {...@@ -3402,6 +3518,15 @@ static void float_min(ZigValue *out_val, ZigValue *op1, ZigValue *op2) {
3402 out_val->data.x_f64 = op1->data.x_f32 < op2->data.x_f64 ? op1->data.x_f64 : op2->data.x_f64;3518 out_val->data.x_f64 = op1->data.x_f32 < op2->data.x_f64 ? op1->data.x_f64 : op2->data.x_f64;
3403 }3519 }
3404 return;3520 return;
3521 case 80:
3522 if (zig_extF80_isNaN(&op1->data.x_f80)) {
3523 out_val->data.x_f80 = op2->data.x_f80;
3524 } else if (zig_extF80_isNaN(&op2->data.x_f80)) {
3525 out_val->data.x_f80 = op1->data.x_f80;
3526 } else {
3527 out_val->data.x_f80 = extF80M_lt(&op1->data.x_f80, &op2->data.x_f80) ? op1->data.x_f80 : op2->data.x_f80;
3528 }
3529 return;
3405 case 128:3530 case 128:
3406 if (zig_f128_isNaN(&op1->data.x_f128)) {3531 if (zig_f128_isNaN(&op1->data.x_f128)) {
3407 out_val->data.x_f128 = op2->data.x_f128;3532 out_val->data.x_f128 = op2->data.x_f128;
...@@ -3434,6 +3559,9 @@ static void float_negate(ZigValue *out_val, ZigValue *op) {...@@ -3434,6 +3559,9 @@ static void float_negate(ZigValue *out_val, ZigValue *op) {
3434 case 64:3559 case 64:
3435 out_val->data.x_f64 = -op->data.x_f64;3560 out_val->data.x_f64 = -op->data.x_f64;
3436 return;3561 return;
3562 case 80:
3563 extF80M_neg(&op->data.x_f80, &out_val->data.x_f80);
3564 return;
3437 case 128:3565 case 128:
3438 f128M_neg(&op->data.x_f128, &out_val->data.x_f128);3566 f128M_neg(&op->data.x_f128, &out_val->data.x_f128);
3439 return;3567 return;
...@@ -3462,6 +3590,9 @@ void float_write_ieee597(ZigValue *op, uint8_t *buf, bool target_is_big_endian)...@@ -3462,6 +3590,9 @@ void float_write_ieee597(ZigValue *op, uint8_t *buf, bool target_is_big_endian)
3462 case 64:3590 case 64:
3463 memcpy(buf, &op->data.x_f64, 8);3591 memcpy(buf, &op->data.x_f64, 8);
3464 break;3592 break;
3593 case 80:
3594 memcpy(buf, &op->data.x_f80, 16);
3595 break;
3465 case 128:3596 case 128:
3466 memcpy(buf, &op->data.x_f128, 16);3597 memcpy(buf, &op->data.x_f128, 16);
3467 break;3598 break;
...@@ -3511,6 +3642,9 @@ void float_read_ieee597(ZigValue *val, uint8_t *buf, bool target_is_big_endian)...@@ -3511,6 +3642,9 @@ void float_read_ieee597(ZigValue *val, uint8_t *buf, bool target_is_big_endian)
3511 case 64:3642 case 64:
3512 memcpy(&val->data.x_f64, ptr, 8);3643 memcpy(&val->data.x_f64, ptr, 8);
3513 return;3644 return;
3645 case 80:
3646 memcpy(&val->data.x_f80, ptr, 16);
3647 return;
3514 case 128:3648 case 128:
3515 memcpy(&val->data.x_f128, ptr, 16);3649 memcpy(&val->data.x_f128, ptr, 16);
3516 return;3650 return;
...@@ -3538,8 +3672,12 @@ static void value_to_bigfloat(BigFloat *out, ZigValue *val) {...@@ -3538,8 +3672,12 @@ static void value_to_bigfloat(BigFloat *out, ZigValue *val) {
3538 case 64:3672 case 64:
3539 bigfloat_init_64(out, val->data.x_f64);3673 bigfloat_init_64(out, val->data.x_f64);
3540 return;3674 return;
3541 case 80:3675 case 80: {
3542 zig_panic("TODO: value_to_bigfloat c_longdouble");3676 float128_t f128_value;
3677 extF80M_to_f128M(&val->data.x_f80, &f128_value);
3678 bigfloat_init_128(out, f128_value);
3679 return;
3680 }
3543 case 128:3681 case 128:
3544 bigfloat_init_128(out, val->data.x_f128);3682 bigfloat_init_128(out, val->data.x_f128);
3545 return;3683 return;
...@@ -3628,8 +3766,14 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, Stage1AirInst *instruc...@@ -3628,8 +3766,14 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, Stage1AirInst *instruc
3628 bigfloat_init_64(&orig_bf, tmp);3766 bigfloat_init_64(&orig_bf, tmp);
3629 break;3767 break;
3630 }3768 }
3631 case 80:3769 case 80: {
3632 zig_panic("TODO: ir_num_lit_fits_in_other_type c_longdouble");3770 float128_t tmp = bigfloat_to_f128(&tmp_bf);
3771 extFloat80_t tmp80;
3772 f128M_to_extF80M(&tmp, &tmp80);
3773 extF80M_to_f128M(&tmp80, &tmp);
3774 bigfloat_init_128(&orig_bf, tmp);
3775 break;
3776 }
3633 case 128: {3777 case 128: {
3634 float128_t tmp = bigfloat_to_f128(&tmp_bf);3778 float128_t tmp = bigfloat_to_f128(&tmp_bf);
3635 bigfloat_init_128(&orig_bf, tmp);3779 bigfloat_init_128(&orig_bf, tmp);
...@@ -3673,8 +3817,15 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, Stage1AirInst *instruc...@@ -3673,8 +3817,15 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, Stage1AirInst *instruc
3673 }3817 }
3674 break;3818 break;
3675 }3819 }
3676 case 80:3820 case 80: {
3677 zig_panic("TODO: ir_num_lit_fits_in_other_type c_longdouble");3821 float16_t tmp = extF80M_to_f16(&const_val->data.x_f80);
3822 extFloat80_t orig;
3823 f16_to_extF80M(tmp, &orig);
3824 if (extF80M_eq(&orig, &const_val->data.x_f80)) {
3825 return true;
3826 }
3827 break;
3828 }
3678 case 128: {3829 case 128: {
3679 float16_t tmp = f128M_to_f16(&const_val->data.x_f128);3830 float16_t tmp = f128M_to_f16(&const_val->data.x_f128);
3680 float128_t orig;3831 float128_t orig;
...@@ -3698,8 +3849,15 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, Stage1AirInst *instruc...@@ -3698,8 +3849,15 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, Stage1AirInst *instruc
3698 }3849 }
3699 break;3850 break;
3700 }3851 }
3701 case 80:3852 case 80: {
3702 zig_panic("TODO: ir_num_lit_fits_in_other_type c_longdouble");3853 float32_t tmp = extF80M_to_f32(&const_val->data.x_f80);
3854 extFloat80_t orig;
3855 f32_to_extF80M(tmp, &orig);
3856 if (extF80M_eq(&orig, &const_val->data.x_f80)) {
3857 return true;
3858 }
3859 break;
3860 }
3703 case 128: {3861 case 128: {
3704 float32_t tmp = f128M_to_f32(&const_val->data.x_f128);3862 float32_t tmp = f128M_to_f32(&const_val->data.x_f128);
3705 float128_t orig;3863 float128_t orig;
...@@ -3715,8 +3873,15 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, Stage1AirInst *instruc...@@ -3715,8 +3873,15 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, Stage1AirInst *instruc
3715 break;3873 break;
3716 case 64:3874 case 64:
3717 switch (const_val->type->data.floating.bit_count) {3875 switch (const_val->type->data.floating.bit_count) {
3718 case 80:3876 case 80: {
3719 zig_panic("TODO: ir_num_lit_fits_in_other_type c_longdouble");3877 float64_t tmp = extF80M_to_f64(&const_val->data.x_f80);
3878 extFloat80_t orig;
3879 f64_to_extF80M(tmp, &orig);
3880 if (extF80M_eq(&orig, &const_val->data.x_f80)) {
3881 return true;
3882 }
3883 break;
3884 }
3720 case 128: {3885 case 128: {
3721 float64_t tmp = f128M_to_f64(&const_val->data.x_f128);3886 float64_t tmp = f128M_to_f64(&const_val->data.x_f128);
3722 float128_t orig;3887 float128_t orig;
...@@ -3730,9 +3895,17 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, Stage1AirInst *instruc...@@ -3730,9 +3895,17 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, Stage1AirInst *instruc
3730 zig_unreachable();3895 zig_unreachable();
3731 }3896 }
3732 break;3897 break;
3733 case 80:3898 case 80: {
3734 assert(const_val->type->data.floating.bit_count == 128);3899 assert(const_val->type->data.floating.bit_count == 128);
3735 zig_panic("TODO: ir_num_lit_fits_in_other_type c_longdouble");3900 extFloat80_t tmp;
3901 f128M_to_extF80M(&const_val->data.x_f128, &tmp);
3902 float128_t orig;
3903 extF80M_to_f128M(&tmp, &orig);
3904 if (f128M_eq(&orig, &const_val->data.x_f128)) {
3905 return true;
3906 }
3907 break;
3908 }
3736 case 128:3909 case 128:
3737 return true;3910 return true;
3738 default:3911 default:
...@@ -5143,8 +5316,11 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, Scope *scope, AstNode...@@ -5143,8 +5316,11 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, Scope *scope, AstNode
5143 case 64:5316 case 64:
5144 const_val->data.x_f64 = bigfloat_to_f64(&other_val->data.x_bigfloat);5317 const_val->data.x_f64 = bigfloat_to_f64(&other_val->data.x_bigfloat);
5145 break;5318 break;
5146 case 80:5319 case 80: {
5147 zig_panic("TODO: eval_const_expr_implicit_cast c_longdouble");5320 float128_t tmp = bigfloat_to_f128(&other_val->data.x_bigfloat);
5321 f128M_to_extF80M(&tmp, &const_val->data.x_f80);
5322 break;
5323 }
5148 case 128:5324 case 128:
5149 const_val->data.x_f128 = bigfloat_to_f128(&other_val->data.x_bigfloat);5325 const_val->data.x_f128 = bigfloat_to_f128(&other_val->data.x_bigfloat);
5150 break;5326 break;
...@@ -5172,8 +5348,11 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, Scope *scope, AstNode...@@ -5172,8 +5348,11 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, Scope *scope, AstNode
5172 case 64:5348 case 64:
5173 const_val->data.x_f64 = bigfloat_to_f64(&bigfloat);5349 const_val->data.x_f64 = bigfloat_to_f64(&bigfloat);
5174 break;5350 break;
5175 case 80:5351 case 80: {
5176 zig_panic("TODO: eval_const_expr_implicit_cast c_longdouble");5352 float128_t tmp = bigfloat_to_f128(&other_val->data.x_bigfloat);
5353 f128M_to_extF80M(&tmp, &const_val->data.x_f80);
5354 break;
5355 }
5177 case 128:5356 case 128:
5178 const_val->data.x_f128 = bigfloat_to_f128(&bigfloat);5357 const_val->data.x_f128 = bigfloat_to_f128(&bigfloat);
5179 break;5358 break;
...@@ -18960,6 +19139,7 @@ static ZigType *type_info_to_type(IrAnalyze *ira, Scope *scope, AstNode *source_...@@ -18960,6 +19139,7 @@ static ZigType *type_info_to_type(IrAnalyze *ira, Scope *scope, AstNode *source_
18960 case 16: return ira->codegen->builtin_types.entry_f16;19139 case 16: return ira->codegen->builtin_types.entry_f16;
18961 case 32: return ira->codegen->builtin_types.entry_f32;19140 case 32: return ira->codegen->builtin_types.entry_f32;
18962 case 64: return ira->codegen->builtin_types.entry_f64;19141 case 64: return ira->codegen->builtin_types.entry_f64;
19142 case 80: return ira->codegen->builtin_types.entry_f80;
18963 case 128: return ira->codegen->builtin_types.entry_f128;19143 case 128: return ira->codegen->builtin_types.entry_f128;
18964 }19144 }
18965 ir_add_error_node(ira, source_node, buf_sprintf("%d-bit float unsupported", bits));19145 ir_add_error_node(ira, source_node, buf_sprintf("%d-bit float unsupported", bits));
...@@ -21943,6 +22123,8 @@ static void ir_eval_mul_add(IrAnalyze *ira, ZigType *float_type,...@@ -21943,6 +22123,8 @@ static void ir_eval_mul_add(IrAnalyze *ira, ZigType *float_type,
21943 case 64:22123 case 64:
21944 out_val->data.x_f64 = fma(op1->data.x_f64, op2->data.x_f64, op3->data.x_f64);22124 out_val->data.x_f64 = fma(op1->data.x_f64, op2->data.x_f64, op3->data.x_f64);
21945 break;22125 break;
22126 case 80:
22127 zig_panic("compiler bug: TODO: implement 'mulAdd' for type 'f80'. See https://github.com/ziglang/zig/issues/4026");
21946 case 128:22128 case 128:
21947 f128M_mulAdd(&op1->data.x_f128, &op2->data.x_f128, &op3->data.x_f128, &out_val->data.x_f128);22129 f128M_mulAdd(&op1->data.x_f128, &op2->data.x_f128, &op3->data.x_f128, &out_val->data.x_f128);
21948 break;22130 break;
...@@ -24156,10 +24338,44 @@ static ErrorMsg *ir_eval_float_op(IrAnalyze *ira, Scope *scope, AstNode *source_...@@ -24156,10 +24338,44 @@ static ErrorMsg *ir_eval_float_op(IrAnalyze *ira, Scope *scope, AstNode *source_
24156 }24338 }
24157 break;24339 break;
24158 }24340 }
24159 case 80:24341 case 80: {
24160 return ir_add_error_node(ira, source_node,24342 extFloat80_t *out = &out_val->data.x_f80;
24161 buf_sprintf("compiler bug: TODO: implement '%s' for type '%s'. See https://github.com/ziglang/zig/issues/4026",24343 extFloat80_t *in = &op->data.x_f80;
24162 float_op_to_name(fop), buf_ptr(&float_type->name)));24344 switch (fop) {
24345 case BuiltinFnIdSqrt:
24346 extF80M_sqrt(in, out);
24347 break;
24348 case BuiltinFnIdFabs:
24349 extF80M_abs(in, out);
24350 break;
24351 case BuiltinFnIdFloor:
24352 extF80M_roundToInt(in, softfloat_round_min, false, out);
24353 break;
24354 case BuiltinFnIdCeil:
24355 extF80M_roundToInt(in, softfloat_round_max, false, out);
24356 break;
24357 case BuiltinFnIdTrunc:
24358 extF80M_trunc(in, out);
24359 break;
24360 case BuiltinFnIdRound:
24361 extF80M_roundToInt(in, softfloat_round_near_maxMag, false, out);
24362 break;
24363 case BuiltinFnIdNearbyInt:
24364 case BuiltinFnIdSin:
24365 case BuiltinFnIdCos:
24366 case BuiltinFnIdExp:
24367 case BuiltinFnIdExp2:
24368 case BuiltinFnIdLog:
24369 case BuiltinFnIdLog10:
24370 case BuiltinFnIdLog2:
24371 return ir_add_error_node(ira, source_node,
24372 buf_sprintf("compiler bug: TODO: implement '%s' for type '%s'. See https://github.com/ziglang/zig/issues/4026",
24373 float_op_to_name(fop), buf_ptr(&float_type->name)));
24374 default:
24375 zig_unreachable();
24376 }
24377 break;
24378 }
24163 case 128: {24379 case 128: {
24164 float128_t *out, *in;24380 float128_t *out, *in;
24165 if (float_type->id == ZigTypeIdComptimeFloat) {24381 if (float_type->id == ZigTypeIdComptimeFloat) {
src/stage1/softfloat.hpp+4
...@@ -56,4 +56,8 @@ static inline bool zig_f128_isNaN(float128_t *aPtr) {...@@ -56,4 +56,8 @@ static inline bool zig_f128_isNaN(float128_t *aPtr) {
56 || ((absA64 == UINT64_C(0x7FFF000000000000)) && lo);56 || ((absA64 == UINT64_C(0x7FFF000000000000)) && lo);
57}57}
5858
59static inline bool zig_extF80_isNaN(extFloat80_t *aPtr) {
60 return (aPtr->signExp & 0x7FFF) == 0x7FFF && aPtr->signif & UINT64_C(0x7FFFFFFFFFFFFFFF);
61}
62
59#endif63#endif
src/stage1/softfloat_ext.cpp+30-8
...@@ -28,13 +28,6 @@ void f128M_trunc(const float128_t *aPtr, float128_t *zPtr) {...@@ -28,13 +28,6 @@ void f128M_trunc(const float128_t *aPtr, float128_t *zPtr) {
28 } 28 }
29}29}
3030
31float16_t f16_neg(const float16_t a) {
32 union { uint16_t ui; float16_t f; } uA;
33 // Toggle the sign bit.
34 uA.ui = a.v ^ (UINT16_C(1) << 15);
35 return uA.f;
36}
37
38void f128M_neg(const float128_t *aPtr, float128_t *zPtr) {31void f128M_neg(const float128_t *aPtr, float128_t *zPtr) {
39 // Toggle the sign bit.32 // Toggle the sign bit.
40#if ZIG_BYTE_ORDER == ZIG_LITTLE_ENDIAN33#if ZIG_BYTE_ORDER == ZIG_LITTLE_ENDIAN
...@@ -46,4 +39,33 @@ void f128M_neg(const float128_t *aPtr, float128_t *zPtr) {...@@ -46,4 +39,33 @@ void f128M_neg(const float128_t *aPtr, float128_t *zPtr) {
46#else39#else
47#error Unsupported endian40#error Unsupported endian
48#endif41#endif
49}
\ No newline at end of file
42}
43
44void extF80M_abs(const extFloat80_t *aPtr, extFloat80_t *zPtr) {
45 // Clear the sign bit.
46 zPtr->signExp = aPtr->signExp & UINT16_C(0x7FFF);
47 zPtr->signif = aPtr->signif;
48}
49
50void extF80M_trunc(const extFloat80_t *aPtr, extFloat80_t *zPtr) {
51 extFloat80_t zero_float;
52 ui32_to_extF80M(0, &zero_float);
53 if (extF80M_lt(aPtr, &zero_float)) {
54 extF80M_roundToInt(aPtr, softfloat_round_max, false, zPtr);
55 } else {
56 extF80M_roundToInt(aPtr, softfloat_round_min, false, zPtr);
57 }
58}
59
60void extF80M_neg(const extFloat80_t *aPtr, extFloat80_t *zPtr) {
61 // Toggle the sign bit.
62 zPtr->signExp = aPtr->signExp ^ UINT16_C(0x8000);
63 zPtr->signif = aPtr->signif;
64}
65
66float16_t f16_neg(const float16_t a) {
67 union { uint16_t ui; float16_t f; } uA;
68 // Toggle the sign bit.
69 uA.ui = a.v ^ (UINT16_C(1) << 15);
70 return uA.f;
71}
src/stage1/softfloat_ext.hpp+4
...@@ -7,6 +7,10 @@ void f128M_abs(const float128_t *aPtr, float128_t *zPtr);...@@ -7,6 +7,10 @@ void f128M_abs(const float128_t *aPtr, float128_t *zPtr);
7void f128M_trunc(const float128_t *aPtr, float128_t *zPtr);7void f128M_trunc(const float128_t *aPtr, float128_t *zPtr);
8void f128M_neg(const float128_t *aPtr, float128_t *zPtr);8void f128M_neg(const float128_t *aPtr, float128_t *zPtr);
99
10void extF80M_abs(const extFloat80_t *aPtr, extFloat80_t *zPtr);
11void extF80M_trunc(const extFloat80_t *aPtr, extFloat80_t *zPtr);
12void extF80M_neg(const extFloat80_t *aPtr, extFloat80_t *zPtr);
13
10float16_t f16_neg(const float16_t a);14float16_t f16_neg(const float16_t a);
1115
12#endif16#endif
\ No newline at end of file
src/stage1/target.cpp+11
...@@ -1019,6 +1019,17 @@ bool target_long_double_is_f128(const ZigTarget *target) {...@@ -1019,6 +1019,17 @@ bool target_long_double_is_f128(const ZigTarget *target) {
1019 }1019 }
1020}1020}
10211021
1022bool target_has_f80(const ZigTarget *target) {
1023 switch (target->arch) {
1024 case ZigLLVM_x86:
1025 case ZigLLVM_x86_64:
1026 return true;
1027
1028 default:
1029 return false;
1030 }
1031}
1032
1022bool target_is_riscv(const ZigTarget *target) {1033bool target_is_riscv(const ZigTarget *target) {
1023 return target->arch == ZigLLVM_riscv32 || target->arch == ZigLLVM_riscv64;1034 return target->arch == ZigLLVM_riscv32 || target->arch == ZigLLVM_riscv64;
1024}1035}
src/stage1/target.hpp+1
...@@ -81,6 +81,7 @@ bool target_is_sparc(const ZigTarget *target);...@@ -81,6 +81,7 @@ bool target_is_sparc(const ZigTarget *target);
81bool target_is_android(const ZigTarget *target);81bool target_is_android(const ZigTarget *target);
82bool target_has_debug_info(const ZigTarget *target);82bool target_has_debug_info(const ZigTarget *target);
83bool target_long_double_is_f128(const ZigTarget *target);83bool target_long_double_is_f128(const ZigTarget *target);
84bool target_has_f80(const ZigTarget *target);
8485
85uint32_t target_arch_pointer_bit_width(ZigLLVM_ArchType arch);86uint32_t target_arch_pointer_bit_width(ZigLLVM_ArchType arch);
86uint32_t target_arch_largest_atomic_bits(ZigLLVM_ArchType arch);87uint32_t target_arch_largest_atomic_bits(ZigLLVM_ArchType arch);
src/type.zig+17
...@@ -58,6 +58,7 @@ pub const Type = extern union {...@@ -58,6 +58,7 @@ pub const Type = extern union {
58 .f16,58 .f16,
59 .f32,59 .f32,
60 .f64,60 .f64,
61 .f80,
61 .f128,62 .f128,
62 .c_longdouble,63 .c_longdouble,
63 => return .Float,64 => return .Float,
...@@ -833,6 +834,7 @@ pub const Type = extern union {...@@ -833,6 +834,7 @@ pub const Type = extern union {
833 .f16,834 .f16,
834 .f32,835 .f32,
835 .f64,836 .f64,
837 .f80,
836 .f128,838 .f128,
837 .bool,839 .bool,
838 .void,840 .void,
...@@ -1053,6 +1055,7 @@ pub const Type = extern union {...@@ -1053,6 +1055,7 @@ pub const Type = extern union {
1053 .f16,1055 .f16,
1054 .f32,1056 .f32,
1055 .f64,1057 .f64,
1058 .f80,
1056 .f128,1059 .f128,
1057 .bool,1060 .bool,
1058 .void,1061 .void,
...@@ -1371,6 +1374,7 @@ pub const Type = extern union {...@@ -1371,6 +1374,7 @@ pub const Type = extern union {
1371 .f16,1374 .f16,
1372 .f32,1375 .f32,
1373 .f64,1376 .f64,
1377 .f80,
1374 .f128,1378 .f128,
1375 .bool,1379 .bool,
1376 .void,1380 .void,
...@@ -1473,6 +1477,7 @@ pub const Type = extern union {...@@ -1473,6 +1477,7 @@ pub const Type = extern union {
1473 .f16 => return Value.initTag(.f16_type),1477 .f16 => return Value.initTag(.f16_type),
1474 .f32 => return Value.initTag(.f32_type),1478 .f32 => return Value.initTag(.f32_type),
1475 .f64 => return Value.initTag(.f64_type),1479 .f64 => return Value.initTag(.f64_type),
1480 .f80 => return Value.initTag(.f80_type),
1476 .f128 => return Value.initTag(.f128_type),1481 .f128 => return Value.initTag(.f128_type),
1477 .bool => return Value.initTag(.bool_type),1482 .bool => return Value.initTag(.bool_type),
1478 .void => return Value.initTag(.void_type),1483 .void => return Value.initTag(.void_type),
...@@ -1543,6 +1548,7 @@ pub const Type = extern union {...@@ -1543,6 +1548,7 @@ pub const Type = extern union {
1543 .f16,1548 .f16,
1544 .f32,1549 .f32,
1545 .f64,1550 .f64,
1551 .f80,
1546 .f128,1552 .f128,
1547 .bool,1553 .bool,
1548 .anyerror,1554 .anyerror,
...@@ -1858,6 +1864,7 @@ pub const Type = extern union {...@@ -1858,6 +1864,7 @@ pub const Type = extern union {
1858 .f16 => return 2,1864 .f16 => return 2,
1859 .f32 => return 4,1865 .f32 => return 4,
1860 .f64 => return 8,1866 .f64 => return 8,
1867 .f80 => return 16,
1861 .f128 => return 16,1868 .f128 => return 16,
1862 .c_longdouble => return 16,1869 .c_longdouble => return 16,
18631870
...@@ -2138,6 +2145,7 @@ pub const Type = extern union {...@@ -2138,6 +2145,7 @@ pub const Type = extern union {
2138 .f16 => return 2,2145 .f16 => return 2,
2139 .f32 => return 4,2146 .f32 => return 4,
2140 .f64 => return 8,2147 .f64 => return 8,
2148 .f80 => return 16,
2141 .f128 => return 16,2149 .f128 => return 16,
2142 .c_longdouble => return 16,2150 .c_longdouble => return 16,
21432151
...@@ -2277,6 +2285,7 @@ pub const Type = extern union {...@@ -2277,6 +2285,7 @@ pub const Type = extern union {
2277 .i16, .u16, .f16 => 16,2285 .i16, .u16, .f16 => 16,
2278 .i32, .u32, .f32 => 32,2286 .i32, .u32, .f32 => 32,
2279 .i64, .u64, .f64 => 64,2287 .i64, .u64, .f64 => 64,
2288 .f80 => 80,
2280 .u128, .i128, .f128 => 128,2289 .u128, .i128, .f128 => 128,
22812290
2282 .isize,2291 .isize,
...@@ -3170,6 +3179,7 @@ pub const Type = extern union {...@@ -3170,6 +3179,7 @@ pub const Type = extern union {
3170 .f16,3179 .f16,
3171 .f32,3180 .f32,
3172 .f64,3181 .f64,
3182 .f80,
3173 .f128,3183 .f128,
3174 .c_longdouble,3184 .c_longdouble,
3175 => true,3185 => true,
...@@ -3184,6 +3194,7 @@ pub const Type = extern union {...@@ -3184,6 +3194,7 @@ pub const Type = extern union {
3184 .f16,3194 .f16,
3185 .f32,3195 .f32,
3186 .f64,3196 .f64,
3197 .f80,
3187 .f128,3198 .f128,
3188 .c_longdouble,3199 .c_longdouble,
3189 .comptime_float,3200 .comptime_float,
...@@ -3200,6 +3211,7 @@ pub const Type = extern union {...@@ -3200,6 +3211,7 @@ pub const Type = extern union {
3200 .f16 => 16,3211 .f16 => 16,
3201 .f32 => 32,3212 .f32 => 32,
3202 .f64 => 64,3213 .f64 => 64,
3214 .f80 => 80,
3203 .f128, .comptime_float => 128,3215 .f128, .comptime_float => 128,
3204 .c_longdouble => CType.longdouble.sizeInBits(target),3216 .c_longdouble => CType.longdouble.sizeInBits(target),
32053217
...@@ -3340,6 +3352,7 @@ pub const Type = extern union {...@@ -3340,6 +3352,7 @@ pub const Type = extern union {
3340 .f16,3352 .f16,
3341 .f32,3353 .f32,
3342 .f64,3354 .f64,
3355 .f80,
3343 .f128,3356 .f128,
3344 .c_longdouble,3357 .c_longdouble,
3345 .comptime_int,3358 .comptime_int,
...@@ -3381,6 +3394,7 @@ pub const Type = extern union {...@@ -3381,6 +3394,7 @@ pub const Type = extern union {
3381 .f16,3394 .f16,
3382 .f32,3395 .f32,
3383 .f64,3396 .f64,
3397 .f80,
3384 .f128,3398 .f128,
3385 .c_longdouble,3399 .c_longdouble,
3386 .comptime_int,3400 .comptime_int,
...@@ -3579,6 +3593,7 @@ pub const Type = extern union {...@@ -3579,6 +3593,7 @@ pub const Type = extern union {
3579 .f16,3593 .f16,
3580 .f32,3594 .f32,
3581 .f64,3595 .f64,
3596 .f80,
3582 .f128,3597 .f128,
3583 .anyopaque,3598 .anyopaque,
3584 .bool,3599 .bool,
...@@ -4334,6 +4349,7 @@ pub const Type = extern union {...@@ -4334,6 +4349,7 @@ pub const Type = extern union {
4334 f16,4349 f16,
4335 f32,4350 f32,
4336 f64,4351 f64,
4352 f80,
4337 f128,4353 f128,
4338 anyopaque,4354 anyopaque,
4339 bool,4355 bool,
...@@ -4453,6 +4469,7 @@ pub const Type = extern union {...@@ -4453,6 +4469,7 @@ pub const Type = extern union {
4453 .f16,4469 .f16,
4454 .f32,4470 .f32,
4455 .f64,4471 .f64,
4472 .f80,
4456 .f128,4473 .f128,
4457 .anyopaque,4474 .anyopaque,
4458 .bool,4475 .bool,
src/value.zig+5
...@@ -47,6 +47,7 @@ pub const Value = extern union {...@@ -47,6 +47,7 @@ pub const Value = extern union {
47 f16_type,47 f16_type,
48 f32_type,48 f32_type,
49 f64_type,49 f64_type,
50 f80_type,
50 f128_type,51 f128_type,
51 anyopaque_type,52 anyopaque_type,
52 bool_type,53 bool_type,
...@@ -205,6 +206,7 @@ pub const Value = extern union {...@@ -205,6 +206,7 @@ pub const Value = extern union {
205 .f16_type,206 .f16_type,
206 .f32_type,207 .f32_type,
207 .f64_type,208 .f64_type,
209 .f80_type,
208 .f128_type,210 .f128_type,
209 .anyopaque_type,211 .anyopaque_type,
210 .bool_type,212 .bool_type,
...@@ -398,6 +400,7 @@ pub const Value = extern union {...@@ -398,6 +400,7 @@ pub const Value = extern union {
398 .f16_type,400 .f16_type,
399 .f32_type,401 .f32_type,
400 .f64_type,402 .f64_type,
403 .f80_type,
401 .f128_type,404 .f128_type,
402 .anyopaque_type,405 .anyopaque_type,
403 .bool_type,406 .bool_type,
...@@ -630,6 +633,7 @@ pub const Value = extern union {...@@ -630,6 +633,7 @@ pub const Value = extern union {
630 .f16_type => return out_stream.writeAll("f16"),633 .f16_type => return out_stream.writeAll("f16"),
631 .f32_type => return out_stream.writeAll("f32"),634 .f32_type => return out_stream.writeAll("f32"),
632 .f64_type => return out_stream.writeAll("f64"),635 .f64_type => return out_stream.writeAll("f64"),
636 .f80_type => return out_stream.writeAll("f80"),
633 .f128_type => return out_stream.writeAll("f128"),637 .f128_type => return out_stream.writeAll("f128"),
634 .anyopaque_type => return out_stream.writeAll("anyopaque"),638 .anyopaque_type => return out_stream.writeAll("anyopaque"),
635 .bool_type => return out_stream.writeAll("bool"),639 .bool_type => return out_stream.writeAll("bool"),
...@@ -824,6 +828,7 @@ pub const Value = extern union {...@@ -824,6 +828,7 @@ pub const Value = extern union {
824 .f16_type => Type.initTag(.f16),828 .f16_type => Type.initTag(.f16),
825 .f32_type => Type.initTag(.f32),829 .f32_type => Type.initTag(.f32),
826 .f64_type => Type.initTag(.f64),830 .f64_type => Type.initTag(.f64),
831 .f80_type => Type.initTag(.f80),
827 .f128_type => Type.initTag(.f128),832 .f128_type => Type.initTag(.f128),
828 .anyopaque_type => Type.initTag(.anyopaque),833 .anyopaque_type => Type.initTag(.anyopaque),
829 .bool_type => Type.initTag(.bool),834 .bool_type => Type.initTag(.bool),
test/behavior/floatop_stage1.zig+81
...@@ -4,6 +4,7 @@ const math = std.math;...@@ -4,6 +4,7 @@ const math = std.math;
4const pi = std.math.pi;4const pi = std.math.pi;
5const e = std.math.e;5const e = std.math.e;
6const Vector = std.meta.Vector;6const Vector = std.meta.Vector;
7const has_f80_rt = @import("builtin").cpu.arch == .x86_64;
78
8const epsilon = 0.000001;9const epsilon = 0.000001;
910
...@@ -27,6 +28,10 @@ fn testSqrt() !void {...@@ -27,6 +28,10 @@ fn testSqrt() !void {
27 var a: f64 = 25;28 var a: f64 = 25;
28 try expect(@sqrt(a) == 5);29 try expect(@sqrt(a) == 5);
29 }30 }
31 if (has_f80_rt) {
32 var a: f80 = 25;
33 try expect(@sqrt(a) == 5);
34 }
30 {35 {
31 const a: comptime_float = 25.0;36 const a: comptime_float = 25.0;
32 try expect(@sqrt(a) == 5.0);37 try expect(@sqrt(a) == 5.0);
...@@ -86,6 +91,10 @@ fn testSin() !void {...@@ -86,6 +91,10 @@ fn testSin() !void {
86 var a: f64 = 0;91 var a: f64 = 0;
87 try expect(@sin(a) == 0);92 try expect(@sin(a) == 0);
88 }93 }
94 // {
95 // var a: f80 = 0;
96 // try expect(@sin(a) == 0);
97 // }
89 {98 {
90 var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 3.3, 4.4 };99 var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 3.3, 4.4 };
91 var result = @sin(v);100 var result = @sin(v);
...@@ -116,6 +125,10 @@ fn testCos() !void {...@@ -116,6 +125,10 @@ fn testCos() !void {
116 var a: f64 = 0;125 var a: f64 = 0;
117 try expect(@cos(a) == 1);126 try expect(@cos(a) == 1);
118 }127 }
128 // {
129 // var a: f80 = 0;
130 // try expect(@cos(a) == 1);
131 // }
119 {132 {
120 var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 3.3, 4.4 };133 var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 3.3, 4.4 };
121 var result = @cos(v);134 var result = @cos(v);
...@@ -146,6 +159,10 @@ fn testExp() !void {...@@ -146,6 +159,10 @@ fn testExp() !void {
146 var a: f64 = 0;159 var a: f64 = 0;
147 try expect(@exp(a) == 1);160 try expect(@exp(a) == 1);
148 }161 }
162 // {
163 // var a: f80 = 0;
164 // try expect(@exp(a) == 1);
165 // }
149 {166 {
150 var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 };167 var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 };
151 var result = @exp(v);168 var result = @exp(v);
...@@ -176,6 +193,10 @@ fn testExp2() !void {...@@ -176,6 +193,10 @@ fn testExp2() !void {
176 var a: f64 = 2;193 var a: f64 = 2;
177 try expect(@exp2(a) == 4);194 try expect(@exp2(a) == 4);
178 }195 }
196 // {
197 // var a: f80 = 2;
198 // try expect(@exp2(a) == 4);
199 // }
179 {200 {
180 var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 };201 var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 };
181 var result = @exp2(v);202 var result = @exp2(v);
...@@ -208,6 +229,10 @@ fn testLog() !void {...@@ -208,6 +229,10 @@ fn testLog() !void {
208 var a: f64 = e;229 var a: f64 = e;
209 try expect(@log(a) == 1 or @log(a) == @bitCast(f64, @as(u64, 0x3ff0000000000000)));230 try expect(@log(a) == 1 or @log(a) == @bitCast(f64, @as(u64, 0x3ff0000000000000)));
210 }231 }
232 // {
233 // var a: f80 = e;
234 // try expect(@log(a) == 1);
235 // }
211 {236 {
212 var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 };237 var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 };
213 var result = @log(v);238 var result = @log(v);
...@@ -238,6 +263,10 @@ fn testLog2() !void {...@@ -238,6 +263,10 @@ fn testLog2() !void {
238 var a: f64 = 4;263 var a: f64 = 4;
239 try expect(@log2(a) == 2);264 try expect(@log2(a) == 2);
240 }265 }
266 // {
267 // var a: f80 = 4;
268 // try expect(@log2(a) == 2);
269 // }
241 {270 {
242 var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 };271 var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 };
243 var result = @log2(v);272 var result = @log2(v);
...@@ -268,6 +297,10 @@ fn testLog10() !void {...@@ -268,6 +297,10 @@ fn testLog10() !void {
268 var a: f64 = 1000;297 var a: f64 = 1000;
269 try expect(@log10(a) == 3);298 try expect(@log10(a) == 3);
270 }299 }
300 // {
301 // var a: f80 = 1000;
302 // try expect(@log10(a) == 3);
303 // }
271 {304 {
272 var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 };305 var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 };
273 var result = @log10(v);306 var result = @log10(v);
...@@ -304,6 +337,12 @@ fn testFabs() !void {...@@ -304,6 +337,12 @@ fn testFabs() !void {
304 try expect(@fabs(a) == 2.5);337 try expect(@fabs(a) == 2.5);
305 try expect(@fabs(b) == 2.5);338 try expect(@fabs(b) == 2.5);
306 }339 }
340 // {
341 // var a: f80 = -2.5;
342 // var b: f80 = 2.5;
343 // try expect(@fabs(a) == 2.5);
344 // try expect(@fabs(b) == 2.5);
345 // }
307 {346 {
308 var v: Vector(4, f32) = [_]f32{ 1.1, -2.2, 0.3, -0.4 };347 var v: Vector(4, f32) = [_]f32{ 1.1, -2.2, 0.3, -0.4 };
309 var result = @fabs(v);348 var result = @fabs(v);
...@@ -334,6 +373,10 @@ fn testFloor() !void {...@@ -334,6 +373,10 @@ fn testFloor() !void {
334 var a: f64 = 3.5;373 var a: f64 = 3.5;
335 try expect(@floor(a) == 3);374 try expect(@floor(a) == 3);
336 }375 }
376 // {
377 // var a: f80 = 3.5;
378 // try expect(@floor(a) == 3);
379 // }
337 {380 {
338 var v: Vector(4, f32) = [_]f32{ 1.1, -2.2, 0.3, -0.4 };381 var v: Vector(4, f32) = [_]f32{ 1.1, -2.2, 0.3, -0.4 };
339 var result = @floor(v);382 var result = @floor(v);
...@@ -364,6 +407,10 @@ fn testCeil() !void {...@@ -364,6 +407,10 @@ fn testCeil() !void {
364 var a: f64 = 3.5;407 var a: f64 = 3.5;
365 try expect(@ceil(a) == 4);408 try expect(@ceil(a) == 4);
366 }409 }
410 // {
411 // var a: f80 = 3.5;
412 // try expect(@ceil(a) == 4);
413 // }
367 {414 {
368 var v: Vector(4, f32) = [_]f32{ 1.1, -2.2, 0.3, -0.4 };415 var v: Vector(4, f32) = [_]f32{ 1.1, -2.2, 0.3, -0.4 };
369 var result = @ceil(v);416 var result = @ceil(v);
...@@ -394,6 +441,10 @@ fn testTrunc() !void {...@@ -394,6 +441,10 @@ fn testTrunc() !void {
394 var a: f64 = -3.5;441 var a: f64 = -3.5;
395 try expect(@trunc(a) == -3);442 try expect(@trunc(a) == -3);
396 }443 }
444 // {
445 // var a: f80 = -3.5;
446 // try expect(@trunc(a) == -3);
447 // }
397 {448 {
398 var v: Vector(4, f32) = [_]f32{ 1.1, -2.2, 0.3, -0.4 };449 var v: Vector(4, f32) = [_]f32{ 1.1, -2.2, 0.3, -0.4 };
399 var result = @trunc(v);450 var result = @trunc(v);
...@@ -403,3 +454,33 @@ fn testTrunc() !void {...@@ -403,3 +454,33 @@ fn testTrunc() !void {
403 try expect(math.approxEqAbs(f32, @trunc(@as(f32, -0.4)), result[3], epsilon));454 try expect(math.approxEqAbs(f32, @trunc(@as(f32, -0.4)), result[3], epsilon));
404 }455 }
405}456}
457
458test "floating point comparisons" {
459 if (has_f80_rt) try testFloatComparisons();
460 comptime try testFloatComparisons();
461}
462
463fn testFloatComparisons() !void {
464 inline for ([_]type{ f16, f32, f64, f80, f128 }) |ty| {
465 // No decimal part
466 {
467 const x: ty = 1.0;
468 try expect(x == 1);
469 try expect(x != 0);
470 try expect(x > 0);
471 try expect(x < 2);
472 try expect(x >= 1);
473 try expect(x <= 1);
474 }
475 // Non-zero decimal part
476 {
477 const x: ty = 1.5;
478 try expect(x != 1);
479 try expect(x != 2);
480 try expect(x > 1);
481 try expect(x < 2);
482 try expect(x >= 1);
483 try expect(x <= 2);
484 }
485 }
486}
test/behavior/math_stage1.zig+19
...@@ -5,6 +5,7 @@ const expectEqualSlices = std.testing.expectEqualSlices;...@@ -5,6 +5,7 @@ const expectEqualSlices = std.testing.expectEqualSlices;
5const maxInt = std.math.maxInt;5const maxInt = std.math.maxInt;
6const minInt = std.math.minInt;6const minInt = std.math.minInt;
7const mem = std.mem;7const mem = std.mem;
8const has_f80_rt = @import("builtin").cpu.arch == .x86_64;
89
9test "allow signed integer division/remainder when values are comptime known and positive or exact" {10test "allow signed integer division/remainder when values are comptime known and positive or exact" {
10 try expect(5 / 3 == 1);11 try expect(5 / 3 == 1);
...@@ -194,6 +195,8 @@ fn testSqrt(comptime T: type, x: T) !void {...@@ -194,6 +195,8 @@ fn testSqrt(comptime T: type, x: T) !void {
194test "@fabs" {195test "@fabs" {
195 try testFabs(f128, 12.0);196 try testFabs(f128, 12.0);
196 comptime try testFabs(f128, 12.0);197 comptime try testFabs(f128, 12.0);
198 if (has_f80_rt) try testFabs(f80, 12.0);
199 // comptime try testFabs(f80, 12.0);
197 try testFabs(f64, 12.0);200 try testFabs(f64, 12.0);
198 comptime try testFabs(f64, 12.0);201 comptime try testFabs(f64, 12.0);
199 try testFabs(f32, 12.0);202 try testFabs(f32, 12.0);
...@@ -217,6 +220,8 @@ test "@floor" {...@@ -217,6 +220,8 @@ test "@floor" {
217 // FIXME: Generates a floorl function call220 // FIXME: Generates a floorl function call
218 // testFloor(f128, 12.0);221 // testFloor(f128, 12.0);
219 comptime try testFloor(f128, 12.0);222 comptime try testFloor(f128, 12.0);
223 // try testFloor(f80, 12.0);
224 comptime try testFloor(f80, 12.0);
220 try testFloor(f64, 12.0);225 try testFloor(f64, 12.0);
221 comptime try testFloor(f64, 12.0);226 comptime try testFloor(f64, 12.0);
222 try testFloor(f32, 12.0);227 try testFloor(f32, 12.0);
...@@ -240,6 +245,8 @@ test "@ceil" {...@@ -240,6 +245,8 @@ test "@ceil" {
240 // FIXME: Generates a ceill function call245 // FIXME: Generates a ceill function call
241 //testCeil(f128, 12.0);246 //testCeil(f128, 12.0);
242 comptime try testCeil(f128, 12.0);247 comptime try testCeil(f128, 12.0);
248 // try testCeil(f80, 12.0);
249 comptime try testCeil(f80, 12.0);
243 try testCeil(f64, 12.0);250 try testCeil(f64, 12.0);
244 comptime try testCeil(f64, 12.0);251 comptime try testCeil(f64, 12.0);
245 try testCeil(f32, 12.0);252 try testCeil(f32, 12.0);
...@@ -263,6 +270,14 @@ test "@trunc" {...@@ -263,6 +270,14 @@ test "@trunc" {
263 // FIXME: Generates a truncl function call270 // FIXME: Generates a truncl function call
264 //testTrunc(f128, 12.0);271 //testTrunc(f128, 12.0);
265 comptime try testTrunc(f128, 12.0);272 comptime try testTrunc(f128, 12.0);
273 // try testTrunc(f80, 12.0);
274 // comptime try testTrunc(f80, 12.0);
275 comptime {
276 const x: f80 = 12.0;
277 const y = x + 0.8;
278 const z = @trunc(y);
279 try expectEqual(x, z);
280 }
266 try testTrunc(f64, 12.0);281 try testTrunc(f64, 12.0);
267 comptime try testTrunc(f64, 12.0);282 comptime try testTrunc(f64, 12.0);
268 try testTrunc(f32, 12.0);283 try testTrunc(f32, 12.0);
...@@ -294,6 +309,8 @@ test "@round" {...@@ -294,6 +309,8 @@ test "@round" {
294 // FIXME: Generates a roundl function call309 // FIXME: Generates a roundl function call
295 //testRound(f128, 12.0);310 //testRound(f128, 12.0);
296 comptime try testRound(f128, 12.0);311 comptime try testRound(f128, 12.0);
312 // try testRound(f80, 12.0);
313 comptime try testRound(f80, 12.0);
297 try testRound(f64, 12.0);314 try testRound(f64, 12.0);
298 comptime try testRound(f64, 12.0);315 comptime try testRound(f64, 12.0);
299 try testRound(f32, 12.0);316 try testRound(f32, 12.0);
...@@ -333,10 +350,12 @@ test "NaN comparison" {...@@ -333,10 +350,12 @@ test "NaN comparison" {
333 try testNanEqNan(f32);350 try testNanEqNan(f32);
334 try testNanEqNan(f64);351 try testNanEqNan(f64);
335 try testNanEqNan(f128);352 try testNanEqNan(f128);
353 if (has_f80_rt) try testNanEqNan(f80);
336 comptime try testNanEqNan(f16);354 comptime try testNanEqNan(f16);
337 comptime try testNanEqNan(f32);355 comptime try testNanEqNan(f32);
338 comptime try testNanEqNan(f64);356 comptime try testNanEqNan(f64);
339 comptime try testNanEqNan(f128);357 comptime try testNanEqNan(f128);
358 // comptime try testNanEqNan(f80);
340}359}
341360
342fn testNanEqNan(comptime F: type) !void {361fn testNanEqNan(comptime F: type) !void {
test/behavior/muladd.zig+6
...@@ -25,6 +25,12 @@ fn testMulAdd() !void {...@@ -25,6 +25,12 @@ fn testMulAdd() !void {
25 var c: f64 = 6.25;25 var c: f64 = 6.25;
26 try expect(@mulAdd(f64, a, b, c) == 20);26 try expect(@mulAdd(f64, a, b, c) == 20);
27 }27 }
28 // {
29 // var a: f16 = 5.5;
30 // var b: f80 = 2.5;
31 // var c: f80 = 6.25;
32 // try expect(@mulAdd(f80, a, b, c) == 20);
33 // }
28 if (builtin.os.tag == .macos and builtin.cpu.arch == .aarch64) {34 if (builtin.os.tag == .macos and builtin.cpu.arch == .aarch64) {
29 // https://github.com/ziglang/zig/issues/990035 // https://github.com/ziglang/zig/issues/9900
30 return error.SkipZigTest;36 return error.SkipZigTest;
test/behavior/type_stage1.zig+2-1
...@@ -13,8 +13,9 @@ test "Type.Float" {...@@ -13,8 +13,9 @@ test "Type.Float" {
13 try testing.expect(f16 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 16 } }));13 try testing.expect(f16 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 16 } }));
14 try testing.expect(f32 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 32 } }));14 try testing.expect(f32 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 32 } }));
15 try testing.expect(f64 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 64 } }));15 try testing.expect(f64 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 64 } }));
16 try testing.expect(f80 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 80 } }));
16 try testing.expect(f128 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 128 } }));17 try testing.expect(f128 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 128 } }));
17 try testTypes(&[_]type{ f16, f32, f64, f128 });18 try testTypes(&[_]type{ f16, f32, f64, f80, f128 });
18}19}
1920
20test "Type.Array" {21test "Type.Array" {
test/behavior/widening.zig+5
...@@ -2,6 +2,7 @@ const std = @import("std");...@@ -2,6 +2,7 @@ const std = @import("std");
2const expect = std.testing.expect;2const expect = std.testing.expect;
3const mem = std.mem;3const mem = std.mem;
4const builtin = @import("builtin");4const builtin = @import("builtin");
5const has_f80_rt = @import("builtin").cpu.arch == .x86_64;
56
6test "integer widening" {7test "integer widening" {
7 var a: u8 = 250;8 var a: u8 = 250;
...@@ -27,6 +28,10 @@ test "float widening" {...@@ -27,6 +28,10 @@ test "float widening" {
27 try expect(a == b);28 try expect(a == b);
28 try expect(b == c);29 try expect(b == c);
29 try expect(c == d);30 try expect(c == d);
31 if (has_f80_rt) {
32 var e: f80 = c;
33 try expect(c == e);
34 }
30}35}
3136
32test "float widening f16 to f128" {37test "float widening f16 to f128" {